lib/jabber/
lib/minify/matthiasmullie-minify/
lib/minify/matthiasmullie-pathconverter/
-lib/flowplayer/
lib/pear/Auth/RADIUS.php
lib/pear/Crypt/CHAP.php
lib/pear/HTML/Common.php
lib/maxmind/GeoIp2/
lib/maxmind/MaxMind/
lib/ltiprovider/
+media/player/videojs/amd/src/
+media/player/videojs/videojs/
mod/assign/feedback/editpdf/fpdi/
repository/s3/S3.php
theme/boost/scss/bootstrap/
lib/jabber/
lib/minify/matthiasmullie-minify/
lib/minify/matthiasmullie-pathconverter/
-lib/flowplayer/
lib/pear/Auth/RADIUS.php
lib/pear/Crypt/CHAP.php
lib/pear/HTML/Common.php
lib/maxmind/GeoIp2/
lib/maxmind/MaxMind/
lib/ltiprovider/
+media/player/videojs/amd/src/
+media/player/videojs/videojs/
mod/assign/feedback/editpdf/fpdi/
repository/s3/S3.php
theme/boost/scss/bootstrap/
--- /dev/null
+<?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/>.
+
+/**
+ * Enrol config manipulation script.
+ *
+ * @package core
+ * @subpackage media
+ * @copyright 2016 Marina Glancy
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+define('NO_OUTPUT_BUFFERING', true);
+
+require_once('../config.php');
+require_once($CFG->libdir.'/adminlib.php');
+
+$action = required_param('action', PARAM_ALPHANUMEXT);
+$media = required_param('media', PARAM_PLUGIN);
+$confirm = optional_param('confirm', 0, PARAM_BOOL);
+
+$PAGE->set_url('/admin/media.php');
+$PAGE->set_context(context_system::instance());
+
+require_login();
+require_capability('moodle/site:config', context_system::instance());
+require_sesskey();
+
+$plugins = core_plugin_manager::instance()->get_plugins_of_type('media');
+$sortorder = array_values(\core\plugininfo\media::get_enabled_plugins());
+
+$return = new moodle_url('/admin/settings.php', array('section' => 'managemediaplayers'));
+
+if (!array_key_exists($media, $plugins)) {
+ redirect($return);
+}
+
+switch ($action) {
+ case 'disable':
+ $plugins[$media]->set_enabled(false);
+ break;
+
+ case 'enable':
+ $plugins[$media]->set_enabled(true);
+ break;
+
+ case 'up':
+ if (($pos = array_search($media, $sortorder)) > 0) {
+ $tmp = $sortorder[$pos - 1];
+ $sortorder[$pos - 1] = $sortorder[$pos];
+ $sortorder[$pos] = $tmp;
+ \core\plugininfo\media::set_enabled_plugins($sortorder);
+ }
+ break;
+
+ case 'down':
+ if ((($pos = array_search($media, $sortorder)) !== false) && ($pos < count($sortorder) - 1)) {
+ $tmp = $sortorder[$pos + 1];
+ $sortorder[$pos + 1] = $sortorder[$pos];
+ $sortorder[$pos] = $tmp;
+ \core\plugininfo\media::set_enabled_plugins($sortorder);
+ }
+ break;
+}
+
+redirect($return);
if (!$processor = $DB->get_record('message_processors', array('id'=>$disable))) {
print_error('outputdoesnotexist', 'message');
}
- $DB->set_field('message_processors', 'enabled', '0', array('id'=>$processor->id)); // Disable output
+ \core_message\api::update_processor_status($processor, 0); // Disable output.
core_plugin_manager::reset_caches();
}
if (!$processor = $DB->get_record('message_processors', array('id'=>$enable))) {
print_error('outputdoesnotexist', 'message');
}
- $DB->set_field('message_processors', 'enabled', '1', array('id'=>$processor->id)); // Enable output
+ \core_message\api::update_processor_status($processor, 1); // Enable output.
core_plugin_manager::reset_caches();
}
}
if ($host = $DB->get_record('mnet_host', array('wwwroot' => $wwwroot))) {
global $CFG;
- return array('wwwroot' => get_string('hostexists', 'mnet', $CFG->wwwroot . '/admin/mnet/peers.php?hostid=' . $host->id));
+ return array('wwwroot' => get_string('hostexists', 'mnet',
+ new moodle_url('/admin/mnet/peers.php', array('hostid' => $host->id))));
}
return array();
}
$mnet_peer->set_id($hostid);
echo $OUTPUT->header();
$currenttab = 'mnetdetails';
- require_once($CFG->dirroot . '/admin/mnet/tabs.php');
+ require_once($CFG->dirroot . '/' . $CFG->admin . '/mnet/tabs.php');
if ($hostid != $CFG->mnet_all_hosts_id) {
$mnet_peer->currentkey = mnet_get_public_key($mnet_peer->wwwroot, $mnet_peer->application);
// we're editing an existing one, so set up the tabs
$currenttab = 'mnetdetails';
$mnet_peer->set_id($id);
- require_once($CFG->dirroot . '/admin/mnet/tabs.php');
+ require_once($CFG->dirroot . '/' . $CFG->admin . '/mnet/tabs.php');
} else if (empty($noreviewform) && ($wwwroot = optional_param('wwwroot', '', PARAM_URL)) && ($applicationid = optional_param('applicationid', 0, PARAM_INT))) {
$application = $DB->get_field('mnet_application', 'name', array('id'=>$applicationid));
$mnet_peer->bootstrap($wwwroot, null, $application);
require(__DIR__.'/../../config.php');
require_once($CFG->libdir.'/adminlib.php');
-require_once($CFG->dirroot . '/admin/mnet/profilefields_form.php');
+require_once($CFG->dirroot . '/' . $CFG->admin .'/mnet/profilefields_form.php');
$mnet = get_mnet_environment();
require_login();
require(__DIR__.'/../../config.php');
require_once($CFG->libdir.'/adminlib.php');
-require_once($CFG->dirroot . '/admin/mnet/services_form.php');
+require_once($CFG->dirroot . '/' . $CFG->admin . '/mnet/services_form.php');
$mnet = get_mnet_environment();
require_login();
echo $OUTPUT->header();
$currenttab = 'mnetservices';
-require_once($CFG->dirroot . '/admin/mnet/tabs.php');
+require_once($CFG->dirroot . '/' . $CFG->admin . '/mnet/tabs.php');
echo $OUTPUT->box_start();
$s = mnet_get_service_info($mnet_peer, false); // basic data only
$mform->set_data($s);
list($context, $course, $cm) = get_context_info_array($contextid);
+$PAGE->set_context($context);
+
require_login($course, false, $cm);
require_capability('moodle/role:review', $context);
require_sesskey();
$risks = $this->get_risks($capability);
- $contents = html_writer::tag('td', $risks, array('class' => 'risks'));
+ $contents = html_writer::tag('td', $risks, array('class' => 'risks text-nowrap'));
$contents .= html_writer::tag('td', $neededroles, array('class' => 'allowedroles'));
$contents .= html_writer::tag('td', $forbiddenroles, array('class' => 'forbiddenroles'));
return $contents;
$query = trim(optional_param('query', '', PARAM_NOTAGS)); // Search string
-$PAGE->set_context(context_system::instance());
+$context = context_system::instance();
+$PAGE->set_context($context);
admin_externalpage_setup('search', '', array('query' => $query)); // now hidden page
$focus = '';
// now we'll deal with the case that the admin has submitted the form with changed settings
-if ($data = data_submitted() and confirm_sesskey()) {
+if ($data = data_submitted() and confirm_sesskey() and isset($data->action) and $data->action == 'save-settings') {
+ require_capability('moodle/site:config', $context);
if (admin_write_settings($data)) {
redirect($PAGE->url, get_string('changessaved'), null, \core\output\notification::NOTIFY_SUCCESS);
}
echo $OUTPUT->notification($statusmsg, 'notifysuccess');
}
-require_once("admin_settings_search_form.php");
-$form = new admin_settings_search_form();
-$form->display();
-echo '<hr>';
+$showsettingslinks = true;
-if ($query) {
- echo admin_search_settings_html($query);
-} else {
+if (has_capability('moodle/site:config', $context)) {
+ require_once("admin_settings_search_form.php");
+ $form = new admin_settings_search_form();
+ $form->display();
+ echo '<hr>';
+ if ($query) {
+ echo admin_search_settings_html($query);
+ $showsettingslinks = false;
+ }
+}
+
+if ($showsettingslinks) {
$node = $PAGE->settingsnav->find('root', navigation_node::TYPE_SITE_ADMIN);
if ($node) {
echo $OUTPUT->render_from_template('core/settings_link_page', ['node' => $node]);
$ADMIN->add('appearance', new admin_externalpage('resetemoticons', new lang_string('emoticonsreset', 'admin'),
new moodle_url('/admin/resetemoticons.php'), 'moodle/site:config', true));
-
- // The "media" subpage.
- $temp = new admin_settingpage('mediasettings', get_string('mediasettings', 'core_media'));
-
- $temp->add(new admin_setting_heading('mediaformats', get_string('mediaformats', 'core_media'),
- format_text(get_string('mediaformats_desc', 'core_media'), FORMAT_MARKDOWN)));
-
- // External services.
- $temp->add(new admin_setting_configcheckbox('core_media_enable_youtube',
- get_string('siteyoutube', 'core_media'), get_string('siteyoutube_desc', 'core_media'), 1));
- $temp->add(new admin_setting_configcheckbox('core_media_enable_vimeo',
- get_string('sitevimeo', 'core_media'), get_string('sitevimeo_desc', 'core_media'), 0));
-
- // Options which require Flash.
- $temp->add(new admin_setting_configcheckbox('core_media_enable_mp3',
- get_string('mp3audio', 'core_media'), get_string('mp3audio_desc', 'core_media'), 1));
- $temp->add(new admin_setting_configcheckbox('core_media_enable_flv',
- get_string('flashvideo', 'core_media'), get_string('flashvideo_desc', 'core_media'), 1));
- $temp->add(new admin_setting_configcheckbox('core_media_enable_swf',
- get_string('flashanimation', 'core_media'), get_string('flashanimation_desc', 'core_media'), 1));
-
- // HTML 5 media.
- // Audio now enabled by default so that it can provide a fallback for mp3 on devices without flash.
- $temp->add(new admin_setting_configcheckbox('core_media_enable_html5audio',
- get_string('html5audio', 'core_media'), get_string('html5audio_desc', 'core_media'), 1));
- // Video now enabled by default so it can provide mp4 support.
- $temp->add(new admin_setting_configcheckbox('core_media_enable_html5video',
- get_string('html5video', 'core_media'), get_string('html5video_desc', 'core_media'), 1));
-
- // Legacy players.
- $temp->add(new admin_setting_heading('legacymediaformats',
- get_string('legacyheading', 'core_media'), get_string('legacyheading_desc', 'core_media')));
-
- $temp->add(new admin_setting_configcheckbox('core_media_enable_qt',
- get_string('legacyquicktime', 'core_media'), get_string('legacyquicktime_desc', 'core_media'), 1));
- $temp->add(new admin_setting_configcheckbox('core_media_enable_wmp',
- get_string('legacywmp', 'core_media'), get_string('legacywmp_desc', 'core_media'), 1));
- $temp->add(new admin_setting_configcheckbox('core_media_enable_rm',
- get_string('legacyreal', 'core_media'), get_string('legacyreal_desc', 'core_media'), 1));
-
- $ADMIN->add('appearance', $temp);
-
-
// "documentation" settingpage
$temp = new admin_settingpage('documentation', new lang_string('moodledocs'));
$temp->add(new admin_setting_configtext('docroot', new lang_string('docroot', 'admin'), new lang_string('configdocroot', 'admin'), 'http://docs.moodle.org', PARAM_URL));
$plugin->load_settings($ADMIN, 'filtersettings', $hassiteconfig);
}
+ // Media players.
+ $ADMIN->add('modules', new admin_category('mediaplayers', new lang_string('type_media_plural', 'plugin')));
+ $temp = new admin_settingpage('managemediaplayers', new lang_string('managemediaplayers', 'media'));
+ $temp->add(new admin_setting_heading('mediaformats', get_string('mediaformats', 'core_media'),
+ format_text(get_string('mediaformats_desc', 'core_media'), FORMAT_MARKDOWN)));
+ $temp->add(new admin_setting_managemediaplayers());
+ $temp->add(new admin_setting_heading('managemediaplayerscommonheading', new lang_string('commonsettings', 'admin'), ''));
+ $temp->add(new admin_setting_configtext('media_default_width',
+ new lang_string('defaultwidth', 'core_media'), new lang_string('defaultwidthdesc', 'core_media'),
+ 400, PARAM_INT, 10));
+ $temp->add(new admin_setting_configtext('media_default_height',
+ new lang_string('defaultheight', 'core_media'), new lang_string('defaultheightdesc', 'core_media'),
+ 300, PARAM_INT, 10));
+ $ADMIN->add('mediaplayers', $temp);
+
+ $plugins = core_plugin_manager::instance()->get_plugins_of_type('media');
+ core_collator::asort_objects_by_property($plugins, 'displayname');
+ foreach ($plugins as $plugin) {
+ /** @var \core\plugininfo\media $plugin */
+ $plugin->load_settings($ADMIN, 'mediaplayers', $hassiteconfig);
+ }
+
// Data format settings.
$ADMIN->add('modules', new admin_category('dataformatsettings', new lang_string('dataformats')));
$temp = new admin_settingpage('managedataformats', new lang_string('managedataformats'));
$temp->add(new admin_setting_configcheckbox('cookiehttponly', new lang_string('cookiehttponly', 'admin'), new lang_string('configcookiehttponly', 'admin'), 0));
$temp->add(new admin_setting_configcheckbox('allowframembedding', new lang_string('allowframembedding', 'admin'), new lang_string('allowframembedding_help', 'admin'), 0));
$temp->add(new admin_setting_configcheckbox('loginpasswordautocomplete', new lang_string('loginpasswordautocomplete', 'admin'), new lang_string('loginpasswordautocomplete_help', 'admin'), 0));
- $ADMIN->add('security', $temp);
+ // Settings elements used by the \core\files\curl_security_helper class.
+ $temp->add(new admin_setting_configmixedhostiplist('curlsecurityblockedhosts',
+ new lang_string('curlsecurityblockedhosts', 'admin'),
+ new lang_string('curlsecurityblockedhostssyntax', 'admin'), ""));
+ $temp->add(new admin_setting_configportlist('curlsecurityallowedport',
+ new lang_string('curlsecurityallowedport', 'admin'),
+ new lang_string('curlsecurityallowedportsyntax', 'admin'), ""));
+ $ADMIN->add('security', $temp);
// "notifications" settingpage
$temp = new admin_settingpage('notifications', new lang_string('notifications', 'admin'));
$ADMIN->add('server', new admin_externalpage('adminregistration', new lang_string('hubs', 'admin'),
"$CFG->wwwroot/$CFG->admin/registration/index.php"));
+// E-mail settings.
+$ADMIN->add('server', new admin_category('email', new lang_string('categoryemail', 'admin')));
+
+$temp = new admin_settingpage('outgoingmailconfig', new lang_string('outgoingmailconfig', 'admin'));
+
+$temp->add(new admin_setting_heading('smtpheading', new lang_string('smtp', 'admin'),
+ new lang_string('smtpdetail', 'admin')));
+$temp->add(new admin_setting_configtext('smtphosts', new lang_string('smtphosts', 'admin'),
+ new lang_string('configsmtphosts', 'admin'), '', PARAM_RAW));
+$options = array('' => new lang_string('none', 'admin'), 'ssl' => 'SSL', 'tls' => 'TLS');
+$temp->add(new admin_setting_configselect('smtpsecure', new lang_string('smtpsecure', 'admin'),
+ new lang_string('configsmtpsecure', 'admin'), '', $options));
+$authtypeoptions = array('LOGIN' => 'LOGIN', 'PLAIN' => 'PLAIN', 'NTLM' => 'NTLM', 'CRAM-MD5' => 'CRAM-MD5');
+$temp->add(new admin_setting_configselect('smtpauthtype', new lang_string('smtpauthtype', 'admin'),
+ new lang_string('configsmtpauthtype', 'admin'), 'LOGIN', $authtypeoptions));
+$temp->add(new admin_setting_configtext('smtpuser', new lang_string('smtpuser', 'admin'),
+ new lang_string('configsmtpuser', 'admin'), '', PARAM_NOTAGS));
+$temp->add(new admin_setting_configpasswordunmask('smtppass', new lang_string('smtppass', 'admin'),
+ new lang_string('configsmtpuser', 'admin'), ''));
+$temp->add(new admin_setting_configtext('smtpmaxbulk', new lang_string('smtpmaxbulk', 'admin'),
+ new lang_string('configsmtpmaxbulk', 'admin'), 1, PARAM_INT));
+$temp->add(new admin_setting_heading('noreplydomainheading', new lang_string('noreplydomain', 'admin'),
+ new lang_string('noreplydomaindetail', 'admin')));
+$temp->add(new admin_setting_configtext('noreplyaddress', new lang_string('noreplyaddress', 'admin'),
+ new lang_string('confignoreplyaddress', 'admin'), 'noreply@' . get_host_from_url($CFG->wwwroot), PARAM_NOTAGS));
+$temp->add(new admin_setting_configtextarea('allowedemaildomains',
+ new lang_string('allowedemaildomains', 'admin'),
+ new lang_string('configallowedemaildomains', 'admin'),
+ ''));
+$temp->add(new admin_setting_heading('emaildoesnotfit', new lang_string('doesnotfit', 'admin'),
+ new lang_string('doesnotfitdetail', 'admin')));
+$charsets = get_list_of_charsets();
+unset($charsets['UTF-8']); // Not needed here.
+$options = array();
+$options['0'] = 'UTF-8';
+$options = array_merge($options, $charsets);
+$temp->add(new admin_setting_configselect('sitemailcharset', new lang_string('sitemailcharset', 'admin'),
+ new lang_string('configsitemailcharset','admin'), '0', $options));
+$temp->add(new admin_setting_configcheckbox('allowusermailcharset', new lang_string('allowusermailcharset', 'admin'),
+ new lang_string('configallowusermailcharset', 'admin'), 0));
+$temp->add(new admin_setting_configcheckbox('allowattachments', new lang_string('allowattachments', 'admin'),
+ new lang_string('configallowattachments', 'admin'), 1));
+$options = array('LF' => 'LF', 'CRLF' => 'CRLF');
+$temp->add(new admin_setting_configselect('mailnewline', new lang_string('mailnewline', 'admin'),
+ new lang_string('configmailnewline', 'admin'), 'LF', $options));
+
+$choices = array(new lang_string('never', 'admin'),
+ new lang_string('always', 'admin'),
+ new lang_string('onlynoreply', 'admin'));
+$temp->add(new admin_setting_configselect('emailfromvia', new lang_string('emailfromvia', 'admin'),
+ new lang_string('configemailfromvia', 'admin'), 1, $choices));
+
+$ADMIN->add('email', $temp);
+
// "update notifications" settingpage
if (empty($CFG->disableupdatenotifications)) {
$temp = new admin_settingpage('updatenotifications', new lang_string('updatenotifications', 'core_admin'));
$ADMIN->add('root', new admin_category('unsupported', new lang_string('unsupported', 'admin'), true));
// hidden search script
-$ADMIN->add('root', new admin_externalpage('search', new lang_string('search', 'admin'), "$CFG->wwwroot/$CFG->admin/search.php", 'moodle/site:config', true));
+$ADMIN->add('root', new admin_externalpage('search', new lang_string('search', 'admin'), "$CFG->wwwroot/$CFG->admin/search.php", 'moodle/site:configview', true));
<form action="{{actionurl}}" method="post" id="adminsettings">
<div>
<input type="hidden" name="sesskey" value="{{sesskey}}">
+ <input type="hidden" name="action" value="save-settings">
</div>
<fieldset>
<div class="clearer"></div>
| HTML format | Student page contents |
And I press "Save"
Then I should see "Student page contents" in the "region-main" "region"
- And I follow "Edit"
+ And I click on "Edit" "link" in the "Administration" "block"
# Select (multi-select) - Checking "I set the field".
- And I follow "Edit settings"
+ And I click on "Edit settings" "link" in the "Administration" "block"
And I expand all fieldsets
# Checkbox - Checking "I set the field".
And I set the field "Display description on course page" to "1"
And I press "Save and return to course"
And I should see "Test this one"
And I follow "Test this one"
- And I follow "Edit settings"
+ And I click on "Edit settings" "link" in the "Administration" "block"
# Checkbox - Checking "the field matches value" and "the following fields match these values".
And the following fields match these values:
| Display description on course page | 1 |
# Select (simple) - Checking "I set the field".
And I set the field "Group mode" to "Separate groups"
And I press "Save and display"
- And I follow "Edit settings"
+ And I click on "Edit settings" "link" in the "Administration" "block"
And the following fields match these values:
| Default format | NWiki |
| Group mode | Separate groups |
And the "available[day]" "field" should be enabled
And the field "deadline[enabled]" matches value "1"
And I press "Save and display"
- And I follow "Edit settings"
+ And I click on "Edit settings" "link" in the "Administration" "block"
And the field "available[enabled]" matches value "1"
And the "available[day]" "field" should be enabled
And the field "deadline[enabled]" matches value "1"
if ($updated) {
$this->info[] = get_string('langupdatecomplete', 'tool_langimport');
+ // The strings have been changed so we need to purge their cache to ensure users see the changes.
+ get_string_manager()->reset_caches();
} else {
$this->info[] = get_string('nolangupdateneeded', 'tool_langimport');
}
Menubar.prototype.setOpenDirection = function() {
var pos = this.menuRoot.offset();
var isRTL = $(document.body).hasClass('dir-rtl');
- var openLeft = false;
+ var openLeft = true;
var heightmenuRoot = this.rootMenus.outerHeight();
var widthmenuRoot = this.rootMenus.outerWidth();
// Sometimes the menuMinWidth is not enough to figure out if menu exceeds the window width.
$mform->addElement('header', 'competenciessection', get_string('competencies', 'core_competency'));
MoodleQuickForm::registerElementType('course_competencies',
- "$CFG->dirroot/admin/tool/lp/classes/course_competencies_form_element.php",
+ "$CFG->dirroot/$CFG->admin/tool/lp/classes/course_competencies_form_element.php",
'tool_lp_course_competencies_form_element');
$cmid = null;
if ($cm = $formwrapper->get_coursemodule()) {
$mform->addElement('course_competencies', 'competencies', get_string('modcompetencies', 'tool_lp'), $options);
$mform->addHelpButton('competencies', 'modcompetencies', 'tool_lp');
MoodleQuickForm::registerElementType('course_competency_rule',
- "$CFG->dirroot/admin/tool/lp/classes/course_competency_rule_form_element.php",
+ "$CFG->dirroot/$CFG->admin/tool/lp/classes/course_competency_rule_form_element.php",
'tool_lp_course_competency_rule_form_element');
// Reuse the same options.
$mform->addElement('course_competency_rule', 'competency_rule', get_string('uponcoursemodulecompletion', 'tool_lp'), $options);
}
.tool-lp-menu.tool-lp-menu-open-left .tool-lp-sub-menu {
- margin-left: -120px;
+ left: auto;
+ right: 0;
}
/** This highlighting is copied from bootstrap - but can be overridden by a theme */
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
+ @template tool_lp/action_selector
+
Select an action to execute.
Classes required for JS:
* choices - List of possible actions
* confirm - Text for button confirms
* cancel - Text for button cancel
- }}
+
+ Example context (json):
+ {
+ "message": "Message",
+ "choices": [
+ { "value": "1", "text": "One" },
+ { "value": "2", "text": "Two" }
+ ],
+ "confirm": "Confirm",
+ "cancel": "Cancel"
+ }
+}}
<div data-region="action-selector">
<div data-region="action-selector-message">
{{message}}<br>
</div><br>
<div data-region="action-selector-radio-buttons">
{{#choices}}
- <input id="action-selection-option-{{value}}" type="radio" name="choice" value="{{value}}"/><label for="action-selection-option-{{value}}">{{text}}</label><br>
+ <input id="action-selection-option-{{value}}" type="radio" class="m-r-1" name="choice" value="{{value}}"/><label for="action-selection-option-{{value}}">{{text}}</label><br>
{{/choices}}
</div><br>
<div data-region="action_selector-buttons">
- <input type="button" data-action="action-selector-confirm" value="{{confirm}}"/>
- <input type="button" data-action="action-selector-cancel" value="{{cancel}}"/>
+ <input type="button" data-action="action-selector-confirm" class="btn btn-primary" value="{{confirm}}"/>
+ <input type="button" data-action="action-selector-cancel" class="btn btn-secondary" value="{{cancel}}"/>
</div>
</div>
* template
* uniqid
+ // This template has no example context because it would trigger real updates to the DB.
Example context (json):
{
}
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
+ @template tool_lp/competencies_move_tree
+
Manage competencies template.
Classes required for JS:
Context variables required for this template:
* framework -
* competencies - array of objects containing id, shortname, idnumber, sortorder, parentid, competencyframeworkid, path
+
+ Example context (json):
+ {
+ "framework": {
+ "shortname":"framework"
+ },
+ "competencies": [
+ { "name": "Competency", "id": 1 }
+ ]
+ }
}}
<div data-region="competencymovetree" >
<label>{{#str}}selectcompetencymovetarget, tool_lp{{/str}}</label>
</ul>
</div>
-<div data-region="move-buttons">
- <input type="button" data-action="move" value="{{#str}}move{{/str}}"/>
- <input type="button" data-action="cancel" value="{{#str}}cancel{{/str}}"/>
+<div data-region="move-buttons" class="pull-xs-right">
+ <input type="button" data-action="move" class="btn btn-primary" value="{{#str}}move{{/str}}"/>
+ <input type="button" data-action="cancel" class="btn btn-secondary" value="{{#str}}cancel{{/str}}"/>
</div>
+<div class="clearfix"></div>
+{{!
+ 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 tool_lp/competencies_tree
+
+ Recursively build a competencies tree.
+
+ Classes required for JS:
+
+ Data attibutes required for JS:
+ * data-enhance=movetree
+
+ Context variables required for this template:
+ * id, shortname, idnumber, sortorder, parentid, competencyframeworkid, path, children
+
+ Example context (json):
+ {
+ "id": 1,
+ "shortname": "short",
+ "idnumber": "SHORT",
+ "sortorder": 1,
+ "parentid": 0,
+ "competencyframeworkid": 1,
+ "path": "/",
+ "haschildren": true,
+ "children": [{
+ "id": 2,
+ "shortname": "child",
+ "idnumber": "CHILD",
+ "sortorder": 1,
+ "parentid": 1,
+ "competencyframeworkid": 1,
+ "path": "/1/",
+ "children": []
+ }]
+ }
+}}
<li data-id="{{id}}">
{{#canmanage}}
<span draggable="true">
-<ul data-enhance="tree">
+{{!
+ 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 tool_lp/competencies_tree_root
+
+ Recursively build a competencies tree.
+
+ Classes required for JS:
+
+ Data attibutes required for JS:
+ * data-enhance=movetree
+
+ Context variables required for this template:
+ * id, shortname, idnumber, sortorder, parentid, competencyframeworkid, path, children
+
+ Example context (json):
+ {
+ "shortname": "short",
+ "haschildren": true,
+ "competencies": [{
+ "id": 2,
+ "shortname": "child",
+ "idnumber": "CHILD",
+ "sortorder": 1,
+ "parentid": 1,
+ "competencyframeworkid": 1,
+ "path": "/1/",
+ "children": []
+ }]
+ }
+}}
+<ul data-enhance="tree" class="competency-tree">
<li><span>{{{shortname}}}</span>
<ul>
{{#competencies}}
+{{!
+ 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 tool_lp/competency_grader
+
+ Template for grading a competency.
+
+ Classes required for JS:
+ None
+
+ Data required for JS:
+ * ratings - list of value, name selected for valid ratings
+
+ Example context (json):
+ {
+ "ratings": [
+ {"name": "Bad", "value": 0, "selected": true},
+ {"name": "OK", "value": 1},
+ {"name": "Good", "value": 2}
+ ]
+ }
+}}
<div class="competency-grader" data-region="competency-grader">
<form>
<div class="content">
<div data-region="rating">
<label for="rating_{{uniqid}}">{{#str}}rating, tool_lp{{/str}}</label>
- <select name="rating" id="rating_{{uniqid}}">
+ <select name="rating" id="rating_{{uniqid}}" class="custom-select">
{{#ratings}}
<option value="{{value}}" {{#selected}}selected{{/selected}}>{{name}}</option>
{{/ratings}}
</select>
</div>
- <div data-region="comment">
+ <div data-region="comment" class="m-t-1">
<label for="comment_{{uniqid}}">{{#str}}ratecomment, tool_lp{{/str}}</label>
- <textarea name="comment" id="comment_{{uniqid}}"></textarea>
+ <textarea name="comment" id="comment_{{uniqid}}" class="form-control m-b-1"></textarea>
</div>
</div>
- <div data-region="footer">
- <div class="pull-right">
- <input type="button" data-action="rate" value="{{#str}}rate, tool_lp{{/str}}" class="btn">
- </div>
- <div>
- <button data-action="cancel" class="btn btn-link">{{#str}}cancel{{/str}}</button>
- </div>
+ <div data-region="footer" class="pull-xs-right">
+ <input type="button" data-action="rate" value="{{#str}}rate, tool_lp{{/str}}" class="btn btn-primary">
+ <button data-action="cancel" class="btn btn-secondary">{{#str}}cancel{{/str}}</button>
</div>
+ <div class="clearfix"></div>
</form>
</div>
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
+ @template tool_lp/competency_path
+
Competency path template.
Classes required for JS:
* framework - The competency framework
* id - competency id
* name - competency idnumber
- * first - true if node is in first position
- * last - true if node is in last position
- * position - the position of the node in the list
* ancestors - array of nodes
* id - competency id
* name - competency idnumber
* first - true if node is in first position
* last - true if node is in last position
- * position - the position of the node in the list
* pluginbaseurl - base url of plugin tool_lp
+
+ Example context (json):
+ {
+ "framework": {
+ "id": "1",
+ "name": "Framework"
+ },
+ "ancestors": [
+ {
+ "id": "1",
+ "name": "C1"
+ },
+ {
+ "id": "1",
+ "name": "C2",
+ "last": true
+ }
+ ]
+ }
}}
<nav id="competency-path-{{uniqid}}">
<small>
+{{!
+ 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 tool_lp/competency_picker
+
+ Show a competency tree and allow picking a competency.
+
+ Context variables required for this template:
+ * frameworks - array of competency framework
+ * id
+ * shortname
+ * idnumber
+ * selected
+
+ * framework - competency framework
+ * id
+ * name
+ * shortname
+ * idnumber
+
+ * competencies - array of nodes
+ * id - competency id
+ * name - competency idnumber
+ * children - array of children
+ * haschildren - boolean
+
+ Example context (json):
+ {
+ "frameworks": [
+ {
+ "id": "1",
+ "shortname": "Framework",
+ "idnumber": "F1"
+ }
+ ],
+ "competencies": [
+ ]
+ }
+}}
<div data-region="competencylinktree">
{{^singleFramework}}
<h3>{{#str}}competencyframeworks, tool_lp{{/str}}</h3>
-<select data-action="chooseframework">
+<select data-action="chooseframework" class="custom-select">
{{#frameworks}}
<option value="{{id}}" {{#selected}}selected="selected"{{/selected}}>{{{shortname}}} <em>{{idnumber}}</em></option>
{{/frameworks}}
</select>
{{/singleFramework}}
-<h3>{{#str}}locatecompetency, tool_lp{{/str}}</h3>
+<h3 class="m-t-1">{{#str}}locatecompetency, tool_lp{{/str}}</h3>
-<form data-region="filtercompetencies" data-frameworkid="{{framework.id}}">
- <label class="accesshide" for="filter{{uniqid}}">{{#str}}search, tool_lp{{/str}}</label>
- <input type="text" id="filter{{uniqid}}" placeholder="{{#str}}search, tool_lp{{/str}}" value="{{search}}">
- <button>{{#pix}}a/search, ,{{#str}}search{{/str}}{{/pix}}</button>
+<form data-region="filtercompetencies" class="form-inline" data-frameworkid="{{framework.id}}">
+ <div class="form-group">
+ <label class="accesshide" for="filter{{uniqid}}">{{#str}}search, tool_lp{{/str}}</label>
+ <input type="text" class="form-control" id="filter{{uniqid}}" placeholder="{{#str}}search, tool_lp{{/str}}" value="{{search}}">
+ <button class="btn btn-secondary">{{#pix}}a/search, ,{{#str}}search{{/str}}{{/pix}}</button>
+ </div>
</form>
-<ul data-enhance="linktree" style="display: none;">
+<ul data-enhance="linktree" style="display: none;" class="m-t-1 competency-tree">
<li><span>{{{framework.shortname}}}</span>
<ul>
{{#competencies}}
</ul>
</li>
</ul>
-<div data-region="link-buttons">
- <input type="button" data-action="add" value="{{#str}}add{{/str}}"/>
- <input type="button" data-action="cancel" value="{{#str}}cancel{{/str}}"/>
+<div data-region="link-buttons" class="m-t-1 pull-xs-right">
+ <input type="button" class="btn btn-primary" data-action="add" value="{{#str}}add{{/str}}"/>
+ <input type="button" class="btn btn-secondary" data-action="cancel" value="{{#str}}cancel{{/str}}"/>
</div>
+<div class="clearfix"></div>
</div>
+{{!
+ 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 tool_lp/competency_picker_competencyform
+
+ Show a competency tree and allow picking a competency.
+
+ Context variables required for this template:
+ * framework - The competency framework
+ * id
+ * name
+ * shortname
+
+ * competencies - array of nodes
+ * id - competency id
+ * name - competency idnumber
+ * children - array of children
+ * haschildren - boolean
+
+ Example context (json):
+ {
+ "framework": {
+ "id": "1",
+ "name": "Framework"
+ },
+ "competencies": [
+ ]
+ }
+}}
<div data-region="competencylinktree">
<h3>{{#str}}locatecompetency, tool_lp{{/str}}</h3>
-<form data-region="filtercompetencies" data-frameworkid="{{framework.id}}">
- <label class="accesshide" for="filter{{uniqid}}">{{#str}}search, tool_lp{{/str}}</label>
- <input type="text" id="filter{{uniqid}}" placeholder="{{#str}}search, tool_lp{{/str}}" value="{{search}}">
- <button>{{#pix}}a/search, ,{{#str}}search{{/str}}{{/pix}}</button>
+<form data-region="filtercompetencies" class="form-inline" data-frameworkid="{{framework.id}}">
+ <div class="form-group">
+ <label class="accesshide" for="filter{{uniqid}}">{{#str}}search, tool_lp{{/str}}</label>
+ <input type="text" class="form-control" id="filter{{uniqid}}" placeholder="{{#str}}search, tool_lp{{/str}}" value="{{search}}">
+ <button class="btn btn-secondary">{{#pix}}a/search, ,{{#str}}search{{/str}}{{/pix}}</button>
+ </div>
</form>
-<ul data-enhance="linktree" style="display: none;">
+<ul data-enhance="linktree" style="display: none;" class="m-t-1 competency-tree">
<li data-id="0"><span>{{{framework.shortname}}}</span>
<ul>
{{#competencies}}
</ul>
</li>
</ul>
-<div data-region="link-buttons">
- <input type="button" data-action="add" value="{{#str}}select{{/str}}"/>
- <input type="button" data-action="cancel" value="{{#str}}cancel{{/str}}"/>
+<div data-region="link-buttons" class="m-t-1 pull-xs-right">
+ <input type="button" class="btn btn-primary" data-action="add" value="{{#str}}select{{/str}}"/>
+ <input type="button" class="btn btn-secondary" data-action="cancel" value="{{#str}}cancel{{/str}}"/>
</div>
+<div class="clearfix"></div>
</div>
+{{!
+ 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 tool_lp/competency_picker_user_plans
+
+ Show a competency tree and allow picking a competency.
+
+ Context variables required for this template:
+ * singlePlan - boolean
+
+ * plans - array of plans
+ * id
+ * selected
+ * name
+
+ * plan
+ * id
+ * name
+
+ * competencies - array of nodes
+ * id - competency id
+ * name - competency idnumber
+ * children - array of children
+ * haschildren - boolean
+
+ Example context (json):
+ {
+ "singlePlan": false,
+ "plans": [
+ {
+ "id": "1",
+ "name": "Plan"
+ }
+ ],
+ "plan": {
+ "id": "1",
+ "name": "Plan"
+ },
+ "competencies": []
+ }
+}}
+
<div data-region="competencylinktree">
{{^singlePlan}}
<h3>{{#str}}learningplans, tool_lp{{/str}}</h3>
- <select data-action="chooseplan">
+ <select data-action="chooseplan" class="custom-select">
{{#plans}}
<option value="{{id}}" {{#selected}}selected="selected"{{/selected}}>{{{name}}}</option>
{{/plans}}
</select>
{{/singlePlan}}
-<h3>{{#str}}locatecompetency, tool_lp{{/str}}</h3>
+<h3 class="m-t-1">{{#str}}locatecompetency, tool_lp{{/str}}</h3>
-<form data-region="filtercompetencies" data-planid="{{plan.id}}">
- <label class="accesshide" for="filter{{uniqid}}">{{#str}}search, tool_lp{{/str}}</label>
- <input type="text" id="filter{{uniqid}}" placeholder="{{#str}}search, tool_lp{{/str}}" value="{{search}}">
- <button>{{#pix}}a/search, ,{{#str}}search{{/str}}{{/pix}}</button>
+<form data-region="filtercompetencies" data-planid="{{plan.id}}" class="form-inline">
+ <div class="form-group">
+ <label class="accesshide" for="filter{{uniqid}}">{{#str}}search, tool_lp{{/str}}</label>
+ <input type="text" class="form-control" id="filter{{uniqid}}" placeholder="{{#str}}search, tool_lp{{/str}}" value="{{search}}">
+ <button class="btn btn-secondary">{{#pix}}a/search, ,{{#str}}search{{/str}}{{/pix}}</button>
+ </div>
</form>
-<ul data-enhance="linktree" style="display: none;">
+<ul data-enhance="linktree" style="display: none;" class="m-t-1 competency-tree">
<li><span>{{{plan.name}}}</span>
<ul>
{{#competencies}}
</li>
</ul>
-<div data-region="link-buttons">
- <input type="button" data-action="add" value="{{#str}}add{{/str}}"/>
- <input type="button" data-action="cancel" value="{{#str}}cancel{{/str}}"/>
+<div data-region="link-buttons" class="m-t-1 pull-xs-right">
+ <input type="button" class="btn btn-primary" data-action="add" value="{{#str}}add{{/str}}"/>
+ <input type="button" class="btn btn-secondary" data-action="cancel" value="{{#str}}cancel{{/str}}"/>
</div>
-
+<div class="clearfix"></div>
</div>
-<div class="pull-right well">
+{{!
+ 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 tool_lp/competency_plan_navigation
+
+ Show an auto-complete for jumping to competencies in a plan.
+
+ Context variables required for this template:
+ * hascompetencies - boolean
+ * competencies - array of competencies
+ * id
+ * shortname
+ * idnumber
+ * selected
+ * userid
+ * competencyid
+ * planid
+
+ // No example context because the JS is connected to webservices
+}}
+<div class="pull-xs-right card card-block">
{{#hascompetencies}}
<span>
<label for="competency-nav-{{uniqid}}" class="accesshide">{{#str}}jumptocompetency, tool_lp{{/str}}</label>
</select>
</span>
{{/hascompetencies}}
-</form>
</div>
{{#js}}
require(['core/form-autocomplete', 'tool_lp/competency_plan_navigation'], function(autocomplete, nav) {
+{{!
+ 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 tool_lp/competency_rule_config
+
+ Configuration dialogue for competency rules.
+
+ Context variables required for this template:
+ * config - boolean
+ * outcomes - array
+ * code
+ * name
+ * selected
+ * rules - array
+ * type
+ * name
+ * selected
+
+ Example context (json):
+ {
+ "config": true,
+ "outcomes": [
+ {
+ "code": "C1",
+ "name": "Complete",
+ "selected": true
+ }
+ ],
+ "rules": [
+ {
+ "type": "Type",
+ "name": "Something happens",
+ "selected": true
+ }
+ ]
+ }
+}}
<div data-region="competencyruleconfig">
<div data-region="content">
{{/config}}
{{#config}}
- <div data-region="rule-base">
- <div data-region="rule-outcome">
+ <div data-region="rule-base" class="form">
+ <div data-region="rule-outcome" class="form-group">
<label>{{#str}}outcome, tool_lp{{/str}}</label>
- <select name="outcome" ng-label="{{#str}}outcome, tool_lp{{/str}}">
+ <select name="outcome" class="custom-select" ng-label="{{#str}}outcome, tool_lp{{/str}}">
{{#outcomes}}
<option value="{{code}}" {{#selected}}selected{{/selected}}>{{name}}</option>
{{/outcomes}}
</select>
</div>
- <div data-region="rule-type">
+ <div data-region="rule-type" class="form-group">
<label>{{#str}}when, tool_lp{{/str}}</label>
- <select name="rule" ng-label="{{#str}}when, tool_lp{{/str}}">
+ <select name="rule" class="custom-select" ng-label="{{#str}}when, tool_lp{{/str}}">
<option value="-1">{{#str}}choosedots{{/str}}</option>
{{#rules}}
<option value="{{type}}" {{#selected}}selected{{/selected}}>{{name}}</option>
{{/config}}
</div>
- <div data-region="footer">
+ <div data-region="footer" class="pull-xs-right">
{{#config}}
- <input type="button" data-action="save" value="{{#str}}savechanges{{/str}}"/>
+ <input type="button" class="btn btn-primary" data-action="save" value="{{#str}}savechanges{{/str}}"/>
{{/config}}
- <input type="button" data-action="cancel" value="{{#str}}cancel{{/str}}"/>
+ <input type="button" class="btn btn-secondary" data-action="cancel" value="{{#str}}cancel{{/str}}"/>
</div>
</div>
+{{!
+ 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 tool_lp/competency_rule_points
+
+ Configuration dialogue for competency points rule.
+
+ Context variables required for this template:
+ * children
+ * id
+ * shortname
+ * points
+ * requiredpoints
+
+ Example context (json):
+ {
+ "children": [
+ {
+ "id": "1",
+ "shortname": "Competency",
+ "points": 2
+ }
+ ],
+ "requiredpoints": 4
+ }
+}}
<div class="competency-rule-points">
<table class="table table-condensed">
<thead>
<th scope="row">{{{shortname}}}</th>
<td>
<label class="accesshide" for="pointsforcompetency-{{id}}">{{#str}}pointsgivenfor, tool_lp, {{{competency.shortname}}}{{/str}}</label>
- <input id="pointsforcompetency-{{id}}" type="number" min="0" value="{{points}}" name="points" />
+ <input id="pointsforcompetency-{{id}}" type="number" min="0" value="{{points}}" name="points" class="form-control"/>
</td>
<td>
<label class="accesshide" for="competency-{{id}}-isrequired">{{#str}}aisrequired, tool_lp, {{{competency.shortname}}}{{/str}}</label>
<tfoot>
<tr>
<th scope="row">{{#str}}totalrequiredtocomplete, tool_lp{{/str}}</th>
- <td><input type="number" min="1" value="{{requiredpoints}}" name="requiredpoints" aria-label="{{#str}}totalrequiredtocomplete, tool_lp{{/str}}"></td>
+ <td><input type="number" min="1" value="{{requiredpoints}}" name="requiredpoints" aria-label="{{#str}}totalrequiredtocomplete, tool_lp{{/str}}" class="form-control"></td>
<td> </td>
</tr>
</tfoot>
+{{!
+ 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 tool_lp/competency_summary
+
+ Summary of a competency
+
+ Context variables required for this template:
+ * competency
+ * id
+ * shortname
+ * idnumber
+ * description
+ * framework
+ * shortname
+ * comppath array of ancestors
+ * showrelatedcompetencies boolean
+ * related
+ * showrule boolean
+ * rule
+ * outcome
+ * type
+
+ Example context (json):
+ {
+ "competency": {
+ "id": 1,
+ "shortname": "C1",
+ "idnumber": "PATH",
+ "description": "Can do something"
+ },
+ "framework": {
+ "shortname": "F1"
+ }
+ }
+}}
<div class='competency-heading'>
<h4 id="competency_link_{{competency.id}}">{{{competency.shortname}}}
<small>{{competency.idnumber}}</small>
}}
{{!
Course competencies template.
+
+ For a full list of the context for this template see the course_competencies_page renderable.
}}
<div data-region="coursecompetenciespage">
<div data-region="actions" class="clearfix">
- <div class="pull-left">
+ <div class="pull-xs-left">
{{#canmanagecoursecompetencies}}
- <button disabled>{{#str}}addcoursecompetencies, tool_lp{{/str}}</button>
+ <button class="btn btn-secondary" disabled>{{#str}}addcoursecompetencies, tool_lp{{/str}}</button>
{{/canmanagecoursecompetencies}}
</div>
</div>
<tr class="drag-samenode" data-id="{{competency.id}}">
<td>
{{#canmanagecoursecompetencies}}
- <span class="drag-handlecontainer pull-left"></span>
- <div class="pull-right">
+ <span class="drag-handlecontainer pull-xs-left"></span>
+ <div class="pull-xs-right">
<a href="#" data-action="delete-competency-link" data-id="{{competency.id}}">
{{#pix}}t/delete, core, {{#str}}delete{{/str}}{{/pix}}
</a>
</div>
+ <div class="clearfix"></div>
{{/canmanagecoursecompetencies}}
{{#competency}}
<a href="{{pluginbaseurl}}user_competency_in_course.php?courseid={{courseid}}&competencyid={{competency.id}}&userid={{gradableuserid}}"
<p>{{{competency.description}}}</p>
{{/competency}}
{{#comppath}}
- <span class="pull-left">{{#str}}path, tool_lp{{/str}} </span>{{> tool_lp/competency_path }}
+ <span class="pull-xs-left">{{#str}}path, tool_lp{{/str}} </span>{{> tool_lp/competency_path }}
{{/comppath}}
{{#usercompetencycourse}}
{{#grade}}
{{/canmanagecoursecompetencies}}
<div data-region="coursecompetencyactivities">
<p>
- <ul class="inline">
+ <ul class="inline list-inline">
{{#coursemodules}}
- <li><a href="{{url}}"><img src="{{iconurl}}"> {{name}} </a></li>
+ <li class="list-inline-item"><a href="{{url}}"><img src="{{iconurl}}"> {{name}} </a></li>
{{/coursemodules}}
{{^coursemodules}}
- <li><span class="alert">{{#str}}noactivities, tool_lp{{/str}}</span></li>
+ <li class="list-inline-item"><span class="alert">{{#str}}noactivities, tool_lp{{/str}}</span></li>
{{/coursemodules}}
</ul>
</p>
+{{!
+ 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 tool_lp/course_competency_settings
+
+ Select an action to execute.
+
+ Classes required for JS:
+ * none
+
+ Data attibutes required for JS:
+ * none
+
+ Context variables required for this template:
+ * courseid
+ * pushratingstouserplans
+
+ Example context (json):
+ {
+ "pushratingstouserplans": false,
+ "courseid": -1
+ }
+}}
<form data-region="coursecompetencysettings">
<input type="hidden" name="courseid" value="{{courseid}}"/>
<fieldset>
</label>
</fieldset>
- <fieldset>
- <center>
- <input type="button" data-action="save" value="{{#str}}savechanges{{/str}}"/>
- <input type="button" data-action="cancel" value="{{#str}}cancel{{/str}}"/>
- </center>
+ <fieldset class="pull-xs-right">
+ <input type="button" class="btn btn-primary" data-action="save" value="{{#str}}savechanges{{/str}}"/>
+ <input type="button" class="btn btn-secondary" data-action="cancel" value="{{#str}}cancel{{/str}}"/>
</fieldset>
+ <div class="clearfix"></div>
</form>
Example context (json):
{
"competencycount": 4,
+ "canbegradedincourse": true,
+ "canmanagecoursecompetencies": true,
"proficientcompetencycount": 3,
"proficientcompetencypercentage": 75,
- "proficientcompetencypercentageformatted": 75.0
+ "proficientcompetencypercentageformatted": 75.0,
+ "leastproficientcount": 1,
+ "leastproficient": [
+ { "id": 1, "shortname": "Comp 1", "idnumber": "C1" }
+ ]
}
}}
}}
<div class="well well-small evidence" data-region="evidence" data-id="{{id}}">
{{#candelete}}
- <div class="pull-right">
+ <div class="pull-xs-right">
<a href="#" data-action="delete-evidence">{{#pix}}t/delete{{/pix}}</a>
</div>
{{/candelete}}
{{/actionuser}}
<strong><time datetime="{{userdate}}">{{userdate}}</time></strong>
{{#grade}}
- <p><span class="label">{{gradename}}</span></p>
+ <p><span class="tag tag-info">{{gradename}}</span></p>
{{/grade}}
<p>{{description}}</p>
{{#note}}
+{{!
+ 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 tool_lp/linked_courses_summary
+
+ Moodle template for the list of linked courses to a competency
+
+ Classes required for JS:
+ * none
+
+ Data attributes required for JS:
+ * none
+
+ Context variables required for this template:
+ * courses array
+ * viewurl
+ * fullname
+ * shortname
+
+ Example context (json):
+ { "courses":
+ [
+ {
+ "viewurl": "http://example.com",
+ "fullname": "Course 1",
+ "shortname": "C1"
+ }
+ ]
+ }
+}}
+
<p>
{{#str}}coursesusingthiscompetency, tool_lp{{/str}}
</p>
{{/canmanage}}
</h2>
<div>{{{framework.description}}}</div>
-<h3>{{#str}}competencies, core_competency{{/str}}</h3>
-<div class="row-fluid">
-<div class="span6">
-<p>
-<form data-region="filtercompetencies" data-frameworkid="{{framework.id}}">
- <label class="accesshide" for="filter{{uniqid}}">{{#str}}search, tool_lp{{/str}}</label>
- <input type="text" id="filter{{uniqid}}" placeholder="{{#str}}search, tool_lp{{/str}}" value="{{search}}">
- <button>{{#pix}}a/search, , {{#str}}search{{/str}}{{/pix}}</button>
-</form>
-</p>
-<ul data-enhance="tree">
- {{> tool_lp/loading }}
-</ul>
-</div>
-
-<div class="span6 well">
-<h4 data-region="selected-competency">{{#str}}selectedcompetency, tool_lp{{/str}}</h4>
-<p data-region="competencyinfo">
-{{#str}}nocompetencyselected, tool_lp{{/str}}
-</p>
-{{#canmanage}}
-<div data-region="competencyactions">
-<button class="btn" data-action="add">{{#pix}}t/add{{/pix}} <span data-region="term"></span></button>
- <span data-region="competencyactionsmenu">
- <ul title="{{#str}}edit{{/str}}" class="competencyactionsmenu">
- <li>
- <a href="#">{{#str}}edit{{/str}}</a><b class="caret"></b>
- <ul class="dropdown-menu">
- <li>
- <a href="#" data-action="edit">
- {{#pix}}t/edit{{/pix}} {{#str}}edit{{/str}}
- </a>
- </li>
- <li>
- <a href="#" data-action="move">
- {{#pix}}t/move{{/pix}} {{#str}}movetonewparent, tool_lp{{/str}}
- </a>
- </li>
- <li>
- <a href="#" data-action="delete">
- {{#pix}}t/delete{{/pix}} {{#str}}delete{{/str}}
- </a>
- </li>
- <li>
- <a href="#" data-action="moveup">
- {{#pix}}t/up{{/pix}} {{#str}}moveup{{/str}}
- </a>
- </li>
- <li>
- <a href="#" data-action="movedown">
- {{#pix}}t/down{{/pix}} {{#str}}movedown{{/str}}
- </a>
- </li>
- <li>
- <a href="#" data-action="linkedcourses">
- {{#pix}}t/viewdetails{{/pix}} {{#str}}linkedcourses, tool_lp{{/str}}
- </a>
- </li>
- <li>
- <a href="#" data-action="relatedcompetencies">
- {{#pix}}t/add{{/pix}} {{#str}}addcrossreferencedcompetency, tool_lp{{/str}}
- </a>
- </li>
- <li>
- <a href="#" data-action="competencyrules">
- {{#pix}}t/edit{{/pix}} {{#str}}competencyrule, tool_lp{{/str}}
- </a>
- </li>
- </ul>
- </li>
+ <h3>{{#str}}competencies, core_competency{{/str}}</h3>
+ <div class="row-fluid">
+ <div class="span6 col-lg-6">
+ <p>
+ <form data-region="filtercompetencies" data-frameworkid="{{framework.id}}" class="form-inline">
+ <div class="form-group">
+ <label class="accesshide" for="filter{{uniqid}}">{{#str}}search, tool_lp{{/str}}</label>
+ <input class="form-control" type="text" id="filter{{uniqid}}" placeholder="{{#str}}search, tool_lp{{/str}}" value="{{search}}">
+ <button class="btn btn-secondary">{{#pix}}a/search, , {{#str}}search{{/str}}{{/pix}}</button>
+ </div>
+ </form>
+ </p>
+ <ul data-enhance="tree" class="competency-tree">
+ {{> tool_lp/loading }}
</ul>
- </span>
-</div>
-</div>
-{{/canmanage}}
+ </div>
+
+ <div class="span6 card col-lg-6">
+ <div class="card-block">
+ <div class="card-title">
+ <h4 data-region="selected-competency">{{#str}}selectedcompetency, tool_lp{{/str}}</h4>
+ <span data-region="competencyactionsmenu" class="pull-xs-right">
+ <ul title="{{#str}}edit{{/str}}" class="competencyactionsmenu">
+ <li>
+ <a href="#">{{#str}}edit{{/str}}</a><b class="caret"></b>
+ <ul class="dropdown-menu">
+ <li class="dropdown-item">
+ <a href="#" data-action="edit">
+ {{#pix}}t/edit{{/pix}} {{#str}}edit{{/str}}
+ </a>
+ </li>
+ <li class="dropdown-item">
+ <a href="#" data-action="move">
+ {{#pix}}t/move{{/pix}} {{#str}}movetonewparent, tool_lp{{/str}}
+ </a>
+ </li>
+ <li class="dropdown-item">
+ <a href="#" data-action="delete">
+ {{#pix}}t/delete{{/pix}} {{#str}}delete{{/str}}
+ </a>
+ </li>
+ <li class="dropdown-item">
+ <a href="#" data-action="moveup">
+ {{#pix}}t/up{{/pix}} {{#str}}moveup{{/str}}
+ </a>
+ </li>
+ <li class="dropdown-item">
+ <a href="#" data-action="movedown">
+ {{#pix}}t/down{{/pix}} {{#str}}movedown{{/str}}
+ </a>
+ </li>
+ <li class="dropdown-item">
+ <a href="#" data-action="linkedcourses">
+ {{#pix}}t/viewdetails{{/pix}} {{#str}}linkedcourses, tool_lp{{/str}}
+ </a>
+ </li>
+ <li class="dropdown-item">
+ <a href="#" data-action="relatedcompetencies">
+ {{#pix}}t/add{{/pix}} {{#str}}addcrossreferencedcompetency, tool_lp{{/str}}
+ </a>
+ </li>
+ <li class="dropdown-item">
+ <a href="#" data-action="competencyrules">
+ {{#pix}}t/edit{{/pix}} {{#str}}competencyrule, tool_lp{{/str}}
+ </a>
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </span>
+ </div>
+ <p data-region="competencyinfo">
+ {{#str}}nocompetencyselected, tool_lp{{/str}}
+ </p>
+ {{#canmanage}}
+ <div data-region="competencyactions">
+ <button class="btn btn-secondary" data-action="add">{{#pix}}t/add{{/pix}} <span data-region="term"></span></button>
+ </div>
+ {{/canmanage}}
+ </div>
+ </div>
+ </div>
</div>
{{#js}}
});
{{/js}}
-</div>
<li>
<a href="#">{{#str}}edit{{/str}}</a><b class="caret"></b>
<ul class="dropdown-menu">
- <li>
+ <li class="dropdown-item">
<a href="{{pluginbaseurl}}/editcompetencyframework.php?id={{id}}&pagecontextid={{pagecontextid}}">
{{#pix}}t/edit{{/pix}} {{#str}}edit{{/str}}
</a>
</li>
- <li>
+ <li class="dropdown-item">
<a data-action="duplicatecompetencyframework" href="#" data-frameworkid="{{id}}">
{{#pix}}t/copy{{/pix}} {{#str}}duplicate{{/str}}
</a>
</li>
- <li>
+ <li class="dropdown-item">
<a data-action="deletecompetencyframework" href="#" data-frameworkid="{{id}}">
{{#pix}}t/delete{{/pix}} {{#str}}delete{{/str}}
</a>
<li>
<a href="#">{{#str}}edit{{/str}}</a><b class="caret"></b>
<ul class="dropdown-menu">
- <li>
+ <li class="dropdown-item">
<a href="{{pluginbaseurl}}/edittemplate.php?id={{id}}&pagecontextid={{pagecontextid}}&return=templates">
{{#pix}}t/edit{{/pix}} {{#str}}edit{{/str}}
</a>
</li>
- <li>
+ <li class="dropdown-item">
<a data-action="duplicatetemplate" data-templateid="{{id}}" href="#">
{{#pix}}t/copy{{/pix}} {{#str}}duplicate{{/str}}
</a>
</li>
- <li>
+ <li class="dropdown-item">
<a href="{{pluginbaseurl}}/template_plans.php?id={{id}}&pagecontextid={{pagecontextid}}">
{{#pix}}t/add{{/pix}} {{#str}}createlearningplans, tool_lp{{/str}}
</a>
</li>
- <li>
+ <li class="dropdown-item">
<a href="{{pluginbaseurl}}/template_cohorts.php?id={{id}}&pagecontextid={{pagecontextid}}">
{{#pix}}t/add{{/pix}} {{#str}}addcohortstosync, tool_lp{{/str}}
</a>
</li>
- <li>
+ <li class="dropdown-item">
<a data-action="deletetemplate" data-templateid="{{id}}" href="#">
{{#pix}}t/delete{{/pix}} {{#str}}delete{{/str}}
</a>
-<p class="alert alert-error">
+{{!
+ 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 tool_lp/no_frameworks_warning
+
+ No frameworks warning template.
+
+ Classes required for JS:
+ None
+
+ Context variables required for this template:
+ None
+ Example context (json):
+ {
+ }
+}}
+<p class="alert alert-danger">
{{#str}}nocompetencyframeworks, tool_lp{{/str}}
</p>
<div data-region="actions" class="clearfix">
<div class="pull-left">
<!-- Button to add competencies to the plan -->
- <button class="btn" data-action="add">{{#pix}}t/add{{/pix}} {{#str}}addcompetency, tool_lp{{/str}}</button>
+ <button class="btn btn-secondary" data-action="add">{{#pix}}t/add{{/pix}} {{#str}}addcompetency, tool_lp{{/str}}</button>
</div>
</div>
{{/plan.canbeedited}}
- <div data-region="plan-summary">
+ <div data-region="plan-summary" class="m-t-1">
{{{plan.description}}}
<dl>
<dt>{{#str}}status, tool_lp{{/str}}</dt>
</div>
{{#plan.commentarea}}
{{#canpostorhascomments}}
- <div data-region="comments">
+ <div data-region="comments" class="m-t-1">
{{>tool_lp/comment_area}}
</div>
{{/canpostorhascomments}}
{{/plan.commentarea}}
- <div data-region="plan-competencies">
+ <div data-region="plan-competencies" class="m-t-1">
<h3>{{#str}}learningplancompetencies, tool_lp{{/str}}</h3>
<table class="generaltable fullwidth managecompetencies">
<thead>
<a href="#">{{#str}}edit{{/str}}</a><b class="caret"></b>
<ul class="dropdown-menu">
{{#usercompetency.isrequestreviewallowed}}
- <li>
+ <li class="dropdown-item">
<a href="#" data-action="request-review">{{#pix}}t/edit, core{{/pix}} {{#str}}requestreview, tool_lp{{/str}}</a>
</li>
{{/usercompetency.isrequestreviewallowed}}
{{#usercompetency.iscancelreviewrequestallowed}}
- <li>
+ <li class="dropdown-item">
<a href="#" data-action="cancel-review-request">{{#pix}}t/edit, core{{/pix}} {{#str}}cancelreviewrequest, tool_lp{{/str}}</a>
</li>
{{/usercompetency.iscancelreviewrequestallowed}}
{{#plan.canbeedited}}
- <li>
+ <li class="dropdown-item">
<a href="#" data-action="delete-competency-link" data-id="{{competency.id}}">{{#pix}}t/delete, core{{/pix}} {{#str}}delete{{/str}}</a>
</li>
{{/plan.canbeedited}}
- <li>
+ <li class="dropdown-item">
<a href="#" data-action="find-courses-link" data-id="{{competency.id}}">{{#pix}}t/preview, core{{/pix}} {{#str}}findcourses, tool_lp{{/str}}</a>
</li>
</ul>
<li>
<a href="#">{{#str}}edit{{/str}}</a><b class="caret"></b>
<ul class="dropdown-menu">
- <li {{^canbeedited}} class="disabled" {{/canbeedited}}>
+ <li class="{{^canbeedited}} disabled {{/canbeedited}} dropdown-item">
<a href="{{#canbeedited}}
{{pluginbaseurl}}/editplan.php?id={{id}}&userid={{userid}}&return=plans
{{/canbeedited}}
</a>
</li>
{{#isreopenallowed}}
- <li>
+ <li class="dropdown-item">
<a data-action="plan-reopen" href="#">
{{#pix}}t/edit{{/pix}} {{#str}}reopenplan, tool_lp{{/str}}
</a>
</li>
{{/isreopenallowed}}
{{#iscompleteallowed}}
- <li>
+ <li class="dropdown-item">
<a data-action="plan-complete" href="#">
{{#pix}}t/edit{{/pix}} {{#str}}completeplan, tool_lp{{/str}}
</a>
</li>
{{/iscompleteallowed}}
{{#isrequestreviewallowed}}
- <li>
+ <li class="dropdown-item">
<a data-action="plan-request-review" href="#">{{#pix}}t/edit{{/pix}} {{#str}}requestreview, tool_lp{{/str}}</a>
</li>
{{/isrequestreviewallowed}}
{{#iscancelreviewrequestallowed}}
- <li>
+ <li class="dropdown-item">
<a data-action="plan-cancel-review-request" href="#">{{#pix}}t/edit{{/pix}} {{#str}}cancelreviewrequest, tool_lp{{/str}}</a>
</li>
{{/iscancelreviewrequestallowed}}
{{#isstartreviewallowed}}
- <li>
+ <li class="dropdown-item">
<a data-action="plan-start-review" href="#">{{#pix}}t/edit{{/pix}} {{#str}}startreview, tool_lp{{/str}}</a>
</li>
{{/isstartreviewallowed}}
{{#isstopreviewallowed}}
- <li>
+ <li class="dropdown-item">
<a data-action="plan-stop-review" href="#">{{#pix}}t/edit{{/pix}} {{#str}}stopreview, tool_lp{{/str}}</a>
</li>
{{/isstopreviewallowed}}
{{#isapproveallowed}}
- <li>
+ <li class="dropdown-item">
<a data-action="plan-approve" href="#">{{#pix}}t/edit{{/pix}} {{#str}}planapprove, tool_lp{{/str}}</a>
</li>
{{/isapproveallowed}}
{{#isunapproveallowed}}
- <li>
+ <li class="dropdown-item">
<a data-action="plan-unapprove" href="#">{{#pix}}t/edit{{/pix}} {{#str}}planunapprove, tool_lp{{/str}}</a>
</li>
{{/isunapproveallowed}}
{{#isunlinkallowed}}
- <li>
+ <li class="dropdown-item">
<a data-action="plan-unlink" href="#">
{{#pix}}t/edit{{/pix}} {{#str}}unlinkplantemplate, tool_lp{{/str}}
</a>
</li>
{{/isunlinkallowed}}
- <li>
+ <li class="dropdown-item">
<a data-action="plan-delete" href="#">
{{#pix}}t/delete{{/pix}} {{#str}}deletethisplan, tool_lp{{/str}}
</a>
{{#js}}
// Initialise the JS.
require(['tool_lp/planactions'],
- function(actionsMod) {
+ function(ActionsMod) {
- var planActions = new actionsMod('plans');
+ var planActions = new ActionsMod('plans');
planActions.enhanceMenubar('.planactions');
});
+{{!
+ 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 tool_lp/related_competencies
+
+ List of related competencies.
+
+ Classes required for JS:
+ * none
+
+ Data attributes required for JS:
+ * none
+
+ Context variables required for this template:
+ * showdeleterelatedaction boolean
+ * relatedcompetencies array
+ * id int
+ * shortname string
+ * idnumber string
+
+ Example context (json):
+ {
+ "showdeleterelatedaction": false,
+ "relatedcompetencies":
+ [
+ {
+ "id": 1,
+ "shortname": "Competency",
+ "idnumber": "C1"
+ }
+ ]
+ }
+
+}}
<div data-region="relatedcompetencies">
<p>
<strong>{{#str}}crossreferencedcompetencies, tool_lp{{/str}}:</strong>
{{#relatedcompetencies}}
<li>
{{#showdeleterelatedaction}}
- <div class="pull-right">
+ <div class="pull-xs-right">
<a href="#" data-action="deleterelation" id="id-related-{{id}}">{{#pix}}t/delete, core, {{#str}}delete{{/str}}{{/pix}}</a>
</div>
{{/showdeleterelatedaction}}
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
}}
{{!
+ @template tool_lp/scale_configuration_page
+
Set scale configuration for the competency framework.
Classes required for JS:
{
"scales": [
{ "id": 1, "name": "Competent" },
- { "id": 2, "name": "Not competent"}
+ { "id": 2, "name": "Not competent" }
]
}
}}
</table>
</div>
-<div data-region="scale-buttons">
- <input type="button" data-action="close" value="{{#str}}closebuttontitle{{/str}}"/>
- <input type="button" data-action="cancel" value="{{#str}}cancel{{/str}}"/>
-</div>
\ No newline at end of file
+<div data-region="scale-buttons" class="m-t-1 pull-xs-right">
+ <input type="button" class="btn btn-secondary" data-action="close" value="{{#str}}closebuttontitle{{/str}}"/>
+ <input type="button" class="btn btn-secondary" data-action="cancel" value="{{#str}}cancel{{/str}}"/>
+</div>
+<div class="clearfix"></div>
{{#canmanagetemplatecompetencies}}
<div data-region="actions" class="clearfix">
<div class="pull-left">
- <button disabled>{{#str}}addtemplatecompetencies, tool_lp{{/str}}</button>
+ <button disabled class="btn btn-secondary">{{#str}}addtemplatecompetencies, tool_lp{{/str}}</button>
</div>
</div>
{{/canmanagetemplatecompetencies}}
- <h3>{{#str}}templatecompetencies, tool_lp{{/str}}</h3>
+ <h3 class="m-t-1">{{#str}}templatecompetencies, tool_lp{{/str}}</h3>
{{#statistics}}
{{> tool_lp/template_statistics }}
{{/statistics}}
<div class="well">
{{#canmanagetemplatecompetencies}}
<span class="drag-handlecontainer pull-left"></span>
- <div class="pull-right">
+ <div class="pull-xs-right">
<a href="#" data-action="delete-competency-link" data-id="{{competency.id}}">{{#pix}}t/delete, core, {{#str}}delete{{/str}}{{/pix}}</a>
</div>
{{/canmanagetemplatecompetencies}}
{{/competency}}
<strong>{{#str}}linkedcourseslist, tool_lp{{/str}}</strong>
{{#hascourses}}
- <ul class="inline">
+ <ul class="inline list-inline">
{{#linkedcourses}}
- <li><a href="{{viewurl}}?id={{id}}">{{{fullname}}} ({{{shortname}}})</a></li>
+ <li class="list-inline-item"><a href="{{viewurl}}?id={{id}}">{{{fullname}}} ({{{shortname}}})</a></li>
{{/linkedcourses}}
</ul>
{{/hascourses}}
Template statistics template.
}}
{{#competencycount}}
-<div data-region="templatestatistics" class="well">
+<div data-region="templatestatistics" class="card">
+ <div class="card-block">
{{< tool_lp/progress_bar}}
{{$progresstext}}
{{#str}}xcompetencieslinkedoutofy, tool_lp, { "x": "{{linkedcompetencycount}}", "y": "{{competencycount}}" } {{/str}}
</div>
</div>
{{/leastproficientcount}}
+ </div>
</div>
{{/competencycount}}
-<div class="pull-right well">
+{{!
+ 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 tool_lp/user_competency_course_navigation
+
+ Show an auto-complete for jumping to competencies in a plan.
+
+ Context variables required for this template:
+ * groupselector - HTML
+ * hasusers
+ * users - array
+ * id
+ * selected
+ * fullname
+ * hascompetencies
+ * competencies - array
+ * id
+ * selected
+ * shortname
+ * idnumber
+
+ // No example context because the JS is connected to webservices
+}}
+<div class="pull-xs-right card card-block">
<p>{{{groupselector}}}</p>
<form class="user-competency-course-navigation">
{{#hasusers}}
- {{reviewer.fullname}}
{{/isstatusinreview}}
- {{#isrequestreviewallowed}}<button data-action="request-review">{{#str}}requestreview, tool_lp{{/str}}</button>{{/isrequestreviewallowed}}
- {{#iscancelreviewrequestallowed}}<button data-action="cancel-review-request">{{#str}}cancelreviewrequest, tool_lp{{/str}}</button>{{/iscancelreviewrequestallowed}}
- {{#isstartreviewallowed}}<button data-action="start-review">{{#str}}startreview, tool_lp{{/str}}</button>{{/isstartreviewallowed}}
- {{#isstopreviewallowed}}<button data-action="stop-review">{{#str}}stopreview, tool_lp{{/str}}</button>{{/isstopreviewallowed}}
+ {{#isrequestreviewallowed}}<button class="btn btn-secondary" data-action="request-review">{{#str}}requestreview, tool_lp{{/str}}</button>{{/isrequestreviewallowed}}
+ {{#iscancelreviewrequestallowed}}<button class="btn btn-secondary" data-action="cancel-review-request">{{#str}}cancelreviewrequest, tool_lp{{/str}}</button>{{/iscancelreviewrequestallowed}}
+ {{#isstartreviewallowed}}<button class="btn btn-secondary" data-action="start-review">{{#str}}startreview, tool_lp{{/str}}</button>{{/isstartreviewallowed}}
+ {{#isstopreviewallowed}}<button class="btn btn-secondary" data-action="stop-review">{{#str}}stopreview, tool_lp{{/str}}</button>{{/isstopreviewallowed}}
</dd>
<dt>{{#str}}proficient, tool_lp{{/str}}</dt>
<dd>
<dt>{{#str}}rating, tool_lp{{/str}}</dt>
<dd>{{gradename}}
{{#cangrade}}
- <button class="btn" id="rate_{{uniqid}}">{{#str}}rate, tool_lp{{/str}}</button>
+ <button class="btn btn-secondary" id="rate_{{uniqid}}">{{#str}}rate, tool_lp{{/str}}</button>
{{/cangrade}}
</dd>
{{#js}}
<dt>{{#str}}activities, tool_lp{{/str}}</dt>
<dd data-region="coursecompetencyactivities">
<p>
- <ul class="inline">
+ <ul class="inline list-inline">
{{#coursemodules}}
- <li><a href="{{url}}"><img src="{{iconurl}}"> {{name}} </a></li>
+ <li class="list-inline-item"><a href="{{url}}"><img src="{{iconurl}}"> {{name}} </a></li>
{{/coursemodules}}
{{^coursemodules}}
- <li><span class="alert">{{#str}}noactivities, tool_lp{{/str}}</span></li>
+ <li class="list-inline-item"><span class="alert">{{#str}}noactivities, tool_lp{{/str}}</span></li>
{{/coursemodules}}
</ul>
</p>
<dt>{{#str}}rating, tool_lp{{/str}}</dt>
<dd>{{gradename}}
{{#cangrade}}
- <button class="btn" id="rate_{{uniqid}}">{{#str}}rate, tool_lp{{/str}}</button>
+ <button class="btn btn-secondary" id="rate_{{uniqid}}">{{#str}}rate, tool_lp{{/str}}</button>
{{/cangrade}}
</dd>
{{/usercompetencycourse}}
- {{reviewer.fullname}}
{{/isstatusinreview}}
- {{#isrequestreviewallowed}}<button data-action="request-review">{{#str}}requestreview, tool_lp{{/str}}</button>{{/isrequestreviewallowed}}
- {{#iscancelreviewrequestallowed}}<button data-action="cancel-review-request">{{#str}}cancelreviewrequest, tool_lp{{/str}}</button>{{/iscancelreviewrequestallowed}}
- {{#isstartreviewallowed}}<button data-action="start-review">{{#str}}startreview, tool_lp{{/str}}</button>{{/isstartreviewallowed}}
- {{#isstopreviewallowed}}<button data-action="stop-review">{{#str}}stopreview, tool_lp{{/str}}</button>{{/isstopreviewallowed}}
+ {{#isrequestreviewallowed}}<button class="btn btn-secondary" data-action="request-review">{{#str}}requestreview, tool_lp{{/str}}</button>{{/isrequestreviewallowed}}
+ {{#iscancelreviewrequestallowed}}<button class="btn btn-secondary" data-action="cancel-review-request">{{#str}}cancelreviewrequest, tool_lp{{/str}}</button>{{/iscancelreviewrequestallowed}}
+ {{#isstartreviewallowed}}<button class="btn btn-secondary" data-action="start-review">{{#str}}startreview, tool_lp{{/str}}</button>{{/isstartreviewallowed}}
+ {{#isstopreviewallowed}}<button class="btn btn-secondary" data-action="stop-review">{{#str}}stopreview, tool_lp{{/str}}</button>{{/isstopreviewallowed}}
</dd>
<dt>{{#str}}proficient, tool_lp{{/str}}</dt>
<dd>
<dt>{{#str}}rating, tool_lp{{/str}}</dt>
<dd>{{gradename}}
{{#cangrade}}
- <button class="btn" id="rate_{{uniqid}}">{{#str}}rate, tool_lp{{/str}}</button>
+ <button class="btn btn-secondary" id="rate_{{uniqid}}">{{#str}}rate, tool_lp{{/str}}</button>
{{/cangrade}}
</dd>
{{#js}}
<li>
<a href="#">{{#str}}edit{{/str}}</a><b class="caret"></b>
<ul class="dropdown-menu">
- <li>
+ <li class="dropdown-item">
<a href="{{pluginbaseurl}}/user_evidence_edit.php?id={{id}}&userid={{userid}}&return=list">
{{#pix}}t/edit{{/pix}} {{#str}}editthisuserevidence, tool_lp{{/str}}
</a>
</li>
{{#userhasplan}}
- <li>
+ <li class="dropdown-item">
<a href="#" data-action="link-competency">
{{#pix}}t/add{{/pix}} {{#str}}linkcompetencies, tool_lp{{/str}}
</a>
</li>
{{/userhasplan}}
- <li>
+ <li class="dropdown-item">
<a data-action="send-competencies-review" href="#">
{{#pix}}t/edit{{/pix}} {{#str}}sendcompetenciestoreview, tool_lp{{/str}}
</a>
</li>
- <li>
+ <li class="dropdown-item">
<a data-action="user-evidence-delete" href="#">
{{#pix}}t/delete{{/pix}} {{#str}}deletethisuserevidence, tool_lp{{/str}}
</a>
{{#js}}
require(['tool_lp/user_evidence_actions'], function(UserEvidenceActions) {
var uea = new UserEvidenceActions('list');
- uea.enhanceMenubar('.user-evidence-actions')
+ uea.enhanceMenubar('.user-evidence-actions');
});
{{/js}}
<div data-region="actions" class="clearfix">
<div class="pull-left">
{{#userhasplan}}
- <button class="btn" data-action="link-competency">{{#pix}}t/add{{/pix}} {{#str}}linkcompetencies, tool_lp{{/str}}</button>
+ <button class="btn btn-secondary m-b-1" data-action="link-competency">{{#pix}}t/add{{/pix}} {{#str}}linkcompetencies, tool_lp{{/str}}</button>
{{/userhasplan}}
</div>
</div>
* @param string $rowname
*/
public function click_on_edit_menu_of_the_row($nodetext, $rowname) {
- $xpathtarget = "//ul//li//ul//li[@class='tool-lp-menu-item']//a[contains(.,'" . $nodetext . "')]";
+ $xpathtarget = "//ul//li//ul//li[contains(concat(' ', @class, ' '), ' tool-lp-menu-item ')]//a[contains(.,'" . $nodetext . "')]";
$this->execute('behat_general::i_click_on_in_the', [get_string('edit'), 'link', $this->escape($rowname), 'table_row']);
$this->execute('behat_general::i_click_on_in_the', [$xpathtarget, 'xpath_element', $this->escape($rowname), 'table_row']);
$PAGE->set_title($title);
$PAGE->set_heading(get_string('pluginname', 'tool_lpmigrate'));
-$output = $PAGE->get_renderer('tool_lpmigrate');
-
-echo $output->header();
-echo $output->heading($title);
-
$form = new \tool_lpmigrate\form\migrate_framework($context);
if ($form->is_cancelled()) {
redirect($url);
+}
+
+$output = $PAGE->get_renderer('tool_lpmigrate');
+echo $output->header();
+echo $output->heading($title);
-} else if ($data = $form->get_data()) {
+if ($data = $form->get_data()) {
// Map competencies from both framework.
$mapper = new \tool_lpmigrate\framework_mapper($data->from, $data->to);
// The message will be sent from the intended user.
$eventdata->courseid = SITEID;
- $eventdata->userfrom = \core_user::get_support_user();
+ $eventdata->userfrom = \core_user::get_noreply_user();
$eventdata->userto = $USER;
$eventdata->subject = $this->get_reply_subject($this->currentmessagedata->envelope->subject);
$eventdata->fullmessage = get_string('invalidrecipientdescription', 'tool_messageinbound', $this->currentmessagedata);
defined('MOODLE_INTERNAL') || die;
if ($hassiteconfig) {
- $category = new admin_category('messageinbound', new lang_string('incomingmailconfiguration', 'tool_messageinbound'));
-
// Create a settings page for all of the mail server settings.
- $settings = new admin_settingpage('messageinbound_mailsettings', new lang_string('mailsettings', 'tool_messageinbound'));
+ $settings = new admin_settingpage('messageinbound_mailsettings',
+ new lang_string('incomingmailconfiguration', 'tool_messageinbound'));
$settings->add(new admin_setting_heading('messageinbound_generalconfiguration',
new lang_string('messageinboundgeneralconfiguration', 'tool_messageinbound'),
new lang_string('messageinboundhostpass', 'tool_messageinbound'),
new lang_string('messageinboundhostpass_desc', 'tool_messageinbound'), ''));
- $category->add('messageinbound', $settings);
-
+ // Add the category to the admin tree.
+ $ADMIN->add('email', $settings);
// Link to the external page for Inbound Message handler configuration.
- $category->add('messageinbound', new admin_externalpage('messageinbound_handlers',
+ $ADMIN->add('email', new admin_externalpage('messageinbound_handlers',
new lang_string('message_handlers', 'tool_messageinbound'),
"$CFG->wwwroot/$CFG->admin/tool/messageinbound/index.php"));
-
- // Add the category to the admin tree.
- $ADMIN->add('server', $category);
}
$string['autologinkeygenerationlockout'] = 'Auto-login key generation is locked out, too much requests in an hour.';
$string['autologinnotallowedtoadmins'] = 'Auto-login is not allowed to site admins';
$string['clickheretolaunchtheapp'] = 'Click here if the app does not open automatically.';
+$string['configmobilecssurl'] = 'A CSS file to customise your mobile app interface.';
$string['enablesmartappbanners'] = 'Enable Smart App Banners';
$string['enablesmartappbanners_desc'] = 'This will display a banner promoting the Moodle Mobile app when visiting the site in Mobile Safari.';
$string['forcedurlscheme'] = 'If you want to allow only your custom branded app to be opened via a browser window, then specify its URL scheme here; otherwise leave the field empty.';
$string['loginintheapp'] = 'Via the app';
$string['logininthebrowser'] = 'Via a browser window (for SSO plugins)';
$string['loginintheembeddedbrowser'] = 'Via an embedded browser (for SSO plugins)';
+$string['mobileapp'] = 'Mobile app';
+$string['mobileappearance'] = 'Mobile appearance';
+$string['mobileauthentication'] = 'Mobile authentication';
+$string['mobilecssurl'] = 'CSS';
+$string['mobilesettings'] = 'Mobile settings';
$string['pluginname'] = 'Moodle Mobile tools';
$string['smartappbanners'] = 'Smart App Banners (iOS only)';
$string['pluginnotenabledorconfigured'] = 'Plugin not enabled or configured.';
core_user::require_active_user($USER);
// Get an existing token or create a new one.
+$timenow = time();
$token = external_generate_token_for_current_user($service);
+$privatetoken = $token->privatetoken;
+external_log_token_request($token);
-// Log token access.
-$DB->set_field('external_tokens', 'lastaccess', time(), array('id' => $token->id));
+// Invalidate the private token if external_generate_token_for_current_user did not create a new token.
+if ($token->timecreated < $timenow) {
+ $privatetoken = null;
+}
-$params = array(
- 'objectid' => $token->id,
-);
-$event = \core\event\webservice_token_sent::create($params);
-$event->add_record_snapshot('external_tokens', $token);
-$event->trigger();
+$siteadmin = has_capability('moodle/site:config', context_system::instance(), $USER->id);
// Passport is generated in the mobile app, so the app opening can be validated using that variable.
// Passports are valid only one time, it's deleted in the app once used.
$siteid = md5($CFG->wwwroot . $passport);
-$apptoken = base64_encode($siteid . ':::' . $token->token);
+$apptoken = $siteid . ':::' . $token->token;
+if ($privatetoken and is_https() and !$siteadmin) {
+ $apptoken .= ':::' . $privatetoken;
+}
+
+$apptoken = base64_encode($apptoken);
// Redirect using the custom URL scheme checking first if a URL scheme is forced in the site settings.
$forcedurlscheme = get_config('tool_mobile', 'forcedurlscheme');
if ($hassiteconfig) {
- $temp = new admin_settingpage('mobile', new lang_string('mobile', 'admin'), 'moodle/site:config', false);
+ $ADMIN->add('root', new admin_category('mobileapp', new lang_string('mobileapp', 'tool_mobile')), 'development');
+
+ $temp = new admin_settingpage('mobilesettings', new lang_string('mobilesettings', 'tool_mobile'), 'moodle/site:config', false);
// We should wait to the installation to finish since we depend on some configuration values that are set once
// the admin user profile is configured.
new lang_string('configenablemobilewebservice', 'admin', $enablemobiledoclink), $default));
}
- $temp->add(new admin_setting_configtext('mobilecssurl', new lang_string('mobilecssurl', 'admin'),
- new lang_string('configmobilecssurl', 'admin'), '', PARAM_URL));
+ $ADMIN->add('mobileapp', $temp);
+
+ // Show only mobile settings if the mobile service is enabled.
+ if (!empty($CFG->enablemobilewebservice)) {
+ // Type of login.
+ $temp = new admin_settingpage('mobileauthentication', new lang_string('mobileauthentication', 'tool_mobile'));
+ $options = array(
+ tool_mobile\api::LOGIN_VIA_APP => new lang_string('loginintheapp', 'tool_mobile'),
+ tool_mobile\api::LOGIN_VIA_BROWSER => new lang_string('logininthebrowser', 'tool_mobile'),
+ tool_mobile\api::LOGIN_VIA_EMBEDDED_BROWSER => new lang_string('loginintheembeddedbrowser', 'tool_mobile'),
+ );
+ $temp->add(new admin_setting_configselect('tool_mobile/typeoflogin',
+ new lang_string('typeoflogin', 'tool_mobile'),
+ new lang_string('typeoflogin_desc', 'tool_mobile'), 1, $options));
+
+ $temp->add(new admin_setting_configtext('tool_mobile/forcedurlscheme',
+ new lang_string('forcedurlscheme_key', 'tool_mobile'),
+ new lang_string('forcedurlscheme', 'tool_mobile'), '', PARAM_NOTAGS));
- // Type of login.
- $options = array(
- tool_mobile\api::LOGIN_VIA_APP => new lang_string('loginintheapp', 'tool_mobile'),
- tool_mobile\api::LOGIN_VIA_BROWSER => new lang_string('logininthebrowser', 'tool_mobile'),
- tool_mobile\api::LOGIN_VIA_EMBEDDED_BROWSER => new lang_string('loginintheembeddedbrowser', 'tool_mobile'),
- );
- $temp->add(new admin_setting_configselect('tool_mobile/typeoflogin',
- new lang_string('typeoflogin', 'tool_mobile'),
- new lang_string('typeoflogin_desc', 'tool_mobile'), 1, $options));
+ $ADMIN->add('mobileapp', $temp);
- $temp->add(new admin_setting_configtext('tool_mobile/forcedurlscheme',
- new lang_string('forcedurlscheme_key', 'tool_mobile'),
- new lang_string('forcedurlscheme', 'tool_mobile'), '', PARAM_NOTAGS));
+ // Appearance related settings.
+ $temp = new admin_settingpage('mobileappearance', new lang_string('mobileappearance', 'tool_mobile'));
- $temp->add(new admin_setting_heading('tool_mobile/smartappbanners',
- new lang_string('smartappbanners', 'tool_mobile'), ''));
+ $temp->add(new admin_setting_configtext('mobilecssurl', new lang_string('mobilecssurl', 'tool_mobile'),
+ new lang_string('configmobilecssurl', 'tool_mobile'), '', PARAM_URL));
- $temp->add(new admin_setting_configcheckbox('tool_mobile/enablesmartappbanners',
- new lang_string('enablesmartappbanners', 'tool_mobile'),
- new lang_string('enablesmartappbanners_desc', 'tool_mobile'), 0));
+ $temp->add(new admin_setting_heading('tool_mobile/smartappbanners',
+ new lang_string('smartappbanners', 'tool_mobile'), ''));
- $temp->add(new admin_setting_configtext('tool_mobile/iosappid', new lang_string('iosappid', 'tool_mobile'),
- new lang_string('iosappid_desc', 'tool_mobile'), '633359593', PARAM_ALPHANUM));
+ $temp->add(new admin_setting_configcheckbox('tool_mobile/enablesmartappbanners',
+ new lang_string('enablesmartappbanners', 'tool_mobile'),
+ new lang_string('enablesmartappbanners_desc', 'tool_mobile'), 0));
- $ADMIN->add('webservicesettings', $temp);
+ $temp->add(new admin_setting_configtext('tool_mobile/iosappid', new lang_string('iosappid', 'tool_mobile'),
+ new lang_string('iosappid_desc', 'tool_mobile'), '633359593', PARAM_ALPHANUM));
+
+ $ADMIN->add('mobileapp', $temp);
+ }
}
$service = $DB->get_record('external_services', array('shortname' => MOODLE_OFFICIAL_MOBILE_SERVICE));
$token = external_generate_token_for_current_user($service);
- $this->assertDebuggingCalled(); // MDL-55992.
// Check we got the private token.
$this->assertTrue(isset($token->privatetoken));
$service = $DB->get_record('external_services', array('shortname' => MOODLE_OFFICIAL_MOBILE_SERVICE));
$token = external_generate_token_for_current_user($service);
- $this->assertDebuggingCalled(); // MDL-55992.
$_GET['wstoken'] = $token->token; // Mock parameters.
$result = external::get_autologin_key($token->privatetoken);
require_once(__DIR__ . '/../../../config.php');
require_once($CFG->libdir.'/adminlib.php');
-require_once($CFG->dirroot . '/admin/tool/monitor/lib.php');
+require_once($CFG->dirroot.'/'.$CFG->admin.'/tool/monitor/lib.php');
$courseid = optional_param('courseid', 0, PARAM_INT);
$action = optional_param('action', '', PARAM_ALPHA);
}
}
+/**
+ * Hook called to check whether async course module deletion should be performed or not.
+ *
+ * @return true if background deletion is required (is the recyclebin is enabled), false otherwise.
+ */
+function tool_recyclebin_course_module_background_deletion_recommended() {
+ if (\tool_recyclebin\course_bin::is_enabled()) {
+ return true;
+ }
+}
+
/**
* Hook called before we delete a course.
*
And I follow "Course 1"
And I turn editing mode on
And I delete "Quiz 1" activity
+ And I run all adhoc tasks
And I navigate to "Recycle bin" node in "Course administration"
And I should see "Quiz 1"
And I click on "Restore" "link" in the "region-main" "region"
| Assignment name | Test assign |
| Description | Test |
And I delete "Test assign" activity
+ And I run all adhoc tasks
And I navigate to "Recycle bin" node in "Course administration"
When I click on "Delete" "link"
Then I should see "Are you sure you want to delete the selected item from the recycle bin?"
| Description | Test 2 |
And I delete "Test assign 1" activity
And I delete "Test assign 2" activity
+ And I run all adhoc tasks
And I navigate to "Recycle bin" node in "Course administration"
And I should see "Test assign 1"
And I should see "Test assign 2"
// Delete the course module.
course_delete_module($this->quiz->cmid);
+ // Now, run the course module deletion adhoc task.
+ phpunit_util::run_all_adhoc_tasks();
+
// Check the course module is now in the recycle bin.
$this->assertEquals(1, $DB->count_records('tool_recyclebin_course'));
// Delete the course module.
course_delete_module($this->quiz->cmid);
+ // Now, run the course module deletion adhoc task.
+ phpunit_util::run_all_adhoc_tasks();
+
// Try purging.
$recyclebin = new \tool_recyclebin\course_bin($this->course->id);
foreach ($recyclebin->get_items() as $item) {
// Delete the quiz.
course_delete_module($this->quiz->cmid);
+ // Now, run the course module deletion adhoc task.
+ phpunit_util::run_all_adhoc_tasks();
+
// Set deleted date to the distant past.
$recyclebin = new \tool_recyclebin\course_bin($this->course->id);
foreach ($recyclebin->get_items() as $item) {
course_delete_module($book->cmid);
+ // Now, run the course module deletion adhoc task.
+ phpunit_util::run_all_adhoc_tasks();
+
// Should have 2 items now.
$this->assertEquals(2, count($recyclebin->get_items()));
*/
var findDocsSection = function(templateSource, templateName) {
+ if (!templateSource) {
+ return false;
+ }
// Find the comment section marked with @template component/template.
var marker = "@template " + templateName,
i = 0,
* @copyright 2015 Damyon Wiese <damyon@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-define(['jquery', 'core/ajax', 'core/log', 'core/notification', 'core/templates'],
- function($, ajax, log, notification, templates) {
+define(['jquery', 'core/ajax', 'core/log', 'core/notification', 'core/templates', 'core/config'],
+ function($, ajax, log, notification, templates, config) {
/**
* The ajax call has returned with a new list of templates.
*
* @method refreshSearch
*/
- var refreshSearch = function() {
+ var refreshSearch = function(themename) {
var componentStr = $('[data-field="component"]').val();
var searchStr = $('[data-field="search"]').val();
// Trigger the search.
+ document.location.hash = searchStr;
ajax.call([
{methodname: 'tool_templatelibrary_list_templates',
- args: {component: componentStr, search: searchStr},
+ args: {component: componentStr, search: searchStr, themename: themename},
done: reloadListTemplate,
fail: notification.exception}
], true, false);
};
var changeHandler = function() {
- queueRefresh(refreshSearch, 400);
+ queueRefresh(refreshSearch.bind(this, config.theme), 400);
};
// Add change handlers to refresh the list.
$('[data-region="list-templates"]').on('change', '[data-field="component"]', changeHandler);
$('[data-region="list-templates"]').on('input', '[data-field="search"]', changeHandler);
- refreshSearch();
+ $('[data-field="search"]').val(document.location.hash.replace('#', ''));
+ refreshSearch(config.theme);
return {};
});
* @return array[string] Where each template is in the form "component/templatename".
*/
public static function list_templates($component = '', $search = '', $themename = '') {
- global $CFG;
+ global $CFG, $PAGE;
+
+ if (empty($themename)) {
+ $themename = $PAGE->theme->name;
+ }
+ $themeconfig = \theme_config::load($themename);
$templatedirs = array();
$results = array();
foreach ($plugintypes as $type => $dir) {
$plugins = core_component::get_plugin_list_with_file($type, 'templates', false);
foreach ($plugins as $plugin => $dir) {
+ if ($type == 'theme' && $plugin != $themename && !in_array($plugin, $themeconfig->parents)) {
+ continue;
+ }
if (!empty($dir) && is_dir($dir)) {
$pluginname = $type . '_' . $plugin;
$dirs = mustache_template_finder::get_template_directories_for_component($pluginname, $themename);
*
* @param string $component The component that holds the template.
* @param string $template The name of the template.
- * @return string the template
+ * @return string the template or false if template doesn't exist.
*/
public static function load_canonical_template($component, $template) {
// Get the list of possible template directories.
}
if ($filename === false) {
- throw new moodle_exception('filenotfound', 'error');
+ // There are occasions where we don't have a core template.
+ return false;
}
$templatestr = file_get_contents($filename);
VALUE_DEFAULT,
''
);
- $params = array('component' => $component, 'search' => $search);
+ $themename = new external_value(
+ PARAM_COMPONENT,
+ 'The current theme',
+ VALUE_DEFAULT,
+ ''
+ );
+ $params = array('component' => $component, 'search' => $search, 'themename' => $themename);
return new external_function_parameters($params);
}
* Loads the list of templates.
* @param string $component Limit the search to a component.
* @param string $search The search string.
+ * @param string $themename The name of theme
* @return array[string]
*/
- public static function list_templates($component, $search) {
+ public static function list_templates($component, $search, $themename = '') {
$params = self::validate_parameters(self::list_templates_parameters(),
array(
'component' => $component,
'search' => $search,
+ 'themename' => $themename,
));
- return api::list_templates($component, $search);
+ return api::list_templates($component, $search, $themename);
}
/**
*
* @param string $component The component that holds the template.
* @param string $template The name of the template.
- * @return string the template
+ * @return string the template, false if template doesn't exist.
*/
public static function load_canonical_template($component, $template) {
$params = self::validate_parameters(self::load_canonical_template_parameters(),
-/**
- * @fileOverview Kickass library to create and place poppers near their reference elements.
- * @version 0.6.4
- * @license
- * Copyright (c) 2016 Federico Zivolo and contributors
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-//
-// Cross module loader
-// Supported: Node, AMD, Browser globals
-//
-;(function (root, factory) {
- if (typeof define === 'function' && define.amd) {
- // AMD. Register as an anonymous module.
- define(factory);
- } else if (typeof module === 'object' && module.exports) {
- // Node. Does not work with strict CommonJS, but
- // only CommonJS-like environments that support module.exports,
- // like Node.
- module.exports = factory();
- } else {
- // Browser globals (root is window)
- root.Popper = factory();
- }
-}(this, function () {
-
- 'use strict';
-
- var root = window;
-
- // default options
- var DEFAULTS = {
- // placement of the popper
- placement: 'bottom',
-
- gpuAcceleration: true,
-
- // shift popper from its origin by the given amount of pixels (can be negative)
- offset: 0,
-
- // the element which will act as boundary of the popper
- boundariesElement: 'viewport',
-
- // amount of pixel used to define a minimum distance between the boundaries and the popper
- boundariesPadding: 5,
-
- // popper will try to prevent overflow following this order,
- // by default, then, it could overflow on the left and on top of the boundariesElement
- preventOverflowOrder: ['left', 'right', 'top', 'bottom'],
-
- // the behavior used by flip to change the placement of the popper
- flipBehavior: 'flip',
-
- arrowElement: '[x-arrow]',
-
- // list of functions used to modify the offsets before they are applied to the popper
- modifiers: [ 'shift', 'offset', 'preventOverflow', 'keepTogether', 'arrow', 'flip', 'applyStyle'],
-
- modifiersIgnored: [],
- };
-
- /**
- * Create a new Popper.js instance
- * @constructor Popper
- * @param {HTMLElement} reference - The reference element used to position the popper
- * @param {HTMLElement|Object} popper
- * The HTML element used as popper, or a configuration used to generate the popper.
- * @param {String} [popper.tagName='div'] The tag name of the generated popper.
- * @param {Array} [popper.classNames=['popper']] Array of classes to apply to the generated popper.
- * @param {Array} [popper.attributes] Array of attributes to apply, specify `attr:value` to assign a value to it.
- * @param {HTMLElement|String} [popper.parent=window.document.body] The parent element, given as HTMLElement or as query string.
- * @param {String} [popper.content=''] The content of the popper, it can be text, html, or node; if it is not text, set `contentType` to `html` or `node`.
- * @param {String} [popper.contentType='text'] If `html`, the `content` will be parsed as HTML. If `node`, it will be appended as-is.
- * @param {String} [popper.arrowTagName='div'] Same as `popper.tagName` but for the arrow element.
- * @param {Array} [popper.arrowClassNames='popper__arrow'] Same as `popper.classNames` but for the arrow element.
- * @param {String} [popper.arrowAttributes=['x-arrow']] Same as `popper.attributes` but for the arrow element.
- * @param {Object} options
- * @param {String} [options.placement=bottom]
- * Placement of the popper accepted values: `top(-start, -end), right(-start, -end), bottom(-start, -right),
- * left(-start, -end)`
- *
- * @param {HTMLElement|String} [options.arrowElement='[x-arrow]']
- * The DOM Node used as arrow for the popper, or a CSS selector used to get the DOM node. It must be child of
- * its parent Popper. Popper.js will apply to the given element the style required to align the arrow with its
- * reference element.
- * By default, it will look for a child node of the popper with the `x-arrow` attribute.
- *
- * @param {Boolean} [options.gpuAcceleration=true]
- * When this property is set to true, the popper position will be applied using CSS3 translate3d, allowing the
- * browser to use the GPU to accelerate the rendering.
- * If set to false, the popper will be placed using `top` and `left` properties, not using the GPU.
- *
- * @param {Number} [options.offset=0]
- * Amount of pixels the popper will be shifted (can be negative).
- *
- * @param {String|Element} [options.boundariesElement='viewport']
- * The element which will define the boundaries of the popper position, the popper will never be placed outside
- * of the defined boundaries (except if `keepTogether` is enabled)
- *
- * @param {Number} [options.boundariesPadding=5]
- * Additional padding for the boundaries
- *
- * @param {Array} [options.preventOverflowOrder=['left', 'right', 'top', 'bottom']]
- * Order used when Popper.js tries to avoid overflows from the boundaries, they will be checked in order,
- * this means that the last ones will never overflow
- *
- * @param {String|Array} [options.flipBehavior='flip']
- * The behavior used by the `flip` modifier to change the placement of the popper when the latter is trying to
- * overlap its reference element. Defining `flip` as value, the placement will be flipped on
- * its axis (`right - left`, `top - bottom`).
- * You can even pass an array of placements (eg: `['right', 'left', 'top']` ) to manually specify
- * how alter the placement when a flip is needed. (eg. in the above example, it would first flip from right to left,
- * then, if even in its new placement, the popper is overlapping its reference element, it will be moved to top)
- *
- * @param {Array} [options.modifiers=[ 'shift', 'offset', 'preventOverflow', 'keepTogether', 'arrow', 'flip', 'applyStyle']]
- * List of functions used to modify the data before they are applied to the popper, add your custom functions
- * to this array to edit the offsets and placement.
- * The function should reflect the @params and @returns of preventOverflow
- *
- * @param {Array} [options.modifiersIgnored=[]]
- * Put here any built-in modifier name you want to exclude from the modifiers list
- * The function should reflect the @params and @returns of preventOverflow
- *
- * @param {Boolean} [options.removeOnDestroy=false]
- * Set to true if you want to automatically remove the popper when you call the `destroy` method.
- */
- function Popper(reference, popper, options) {
- this._reference = reference.jquery ? reference[0] : reference;
- this.state = { onCreateCalled: false };
-
- // if the popper variable is a configuration object, parse it to generate an HTMLElement
- // generate a default popper if is not defined
- var isNotDefined = typeof popper === 'undefined' || popper === null;
- var isConfig = popper && Object.prototype.toString.call(popper) === '[object Object]';
- if (isNotDefined || isConfig) {
- this._popper = this.parse(isConfig ? popper : {});
- }
- // otherwise, use the given HTMLElement as popper
- else {
- this._popper = popper.jquery ? popper[0] : popper;
- }
-
- // with {} we create a new object with the options inside it
- this._options = Object.assign({}, DEFAULTS, options);
-
- // refactoring modifiers' list
- this._options.modifiers = this._options.modifiers.map(function(modifier){
- // remove ignored modifiers
- if (this._options.modifiersIgnored.indexOf(modifier) !== -1) return;
-
- // set the x-placement attribute before everything else because it could be used to add margins to the popper
- // margins needs to be calculated to get the correct popper offsets
- if (modifier === 'applyStyle') {
- this._popper.setAttribute('x-placement', this._options.placement);
- }
-
- // return predefined modifier identified by string or keep the custom one
- return this.modifiers[modifier] || modifier;
- }.bind(this));
-
- // make sure to apply the popper position before any computation
- this.state.position = this._getPosition(this._popper, this._reference);
- setStyle(this._popper, { position: this.state.position});
-
- // determine how we should set the origin of offsets
- this.state.isParentTransformed = this._getIsParentTransformed(this._popper);
-
- // fire the first update to position the popper in the right place
- this.update();
-
- // setup event listeners, they will take care of update the position in specific situations
- this._setupEventListeners();
- return this;
- }
-
-
- //
- // Methods
- //
- /**
- * Destroy the popper
- * @method
- * @memberof Popper
- */
- Popper.prototype.destroy = function() {
- this._popper.removeAttribute('x-placement');
- this._popper.style.left = '';
- this._popper.style.position = '';
- this._popper.style.top = '';
- this._popper.style[getSupportedPropertyName('transform')] = '';
- this._removeEventListeners();
-
- // remove the popper if user explicity asked for the deletion on destroy
- if (this._options.removeOnDestroy) {
- this._popper.parentNode.removeChild(this._popper);
- }
- return this;
- };
-
- /**
- * Updates the position of the popper, computing the new offsets and applying the new style
- * @method
- * @memberof Popper
- */
- Popper.prototype.update = function() {
- var data = { instance: this, styles: {} };
-
- // make sure to apply the popper position before any computation
- this.state.position = this._getPosition(this._popper, this._reference);
- setStyle(this._popper, { position: this.state.position});
-
- // to avoid useless computations we throttle the popper position refresh to 60fps
- root.requestAnimationFrame(function() {
- var now = root.performance.now();
- if(now - this.state.lastFrame <= 16) {
- // this update fired to early! drop it
- return;
- }
- this.state.lastFrame = now;
-
- // store placement inside the data object, modifiers will be able to edit `placement` if needed
- // and refer to _originalPlacement to know the original value
- data.placement = this._options.placement;
- data._originalPlacement = this._options.placement;
-
- // compute the popper and trigger offsets and put them inside data.offsets
- data.offsets = this._getOffsets(this._popper, this._reference, data.placement);
-
- // get boundaries
- data.boundaries = this._getBoundaries(data, this._options.boundariesPadding, this._options.boundariesElement);
-
- data = this.runModifiers(data, this._options.modifiers);
-
- if (!isFunction(this.state.createCalback)) {
- this.state.onCreateCalled = true;
- }
- if (!this.state.onCreateCalled) {
- this.state.onCreateCalled = true;
- if (isFunction(this.state.createCalback)) {
- this.state.createCalback(this);
- }
- } else if (isFunction(this.state.updateCallback)) {
- this.state.updateCallback(data);
- }
- }.bind(this));
- };
-
- /**
- * If a function is passed, it will be executed after the initialization of popper with as first argument the Popper instance.
- * @method
- * @memberof Popper
- * @param {Function} callback
- */
- Popper.prototype.onCreate = function(callback) {
- // the createCallbacks return as first argument the popper instance
- this.state.createCalback = callback;
- return this;
- };
-
- /**
- * If a function is passed, it will be executed after each update of popper with as first argument the set of coordinates and informations
- * used to style popper and its arrow.
- * NOTE: it doesn't get fired on the first call of the `Popper.update()` method inside the `Popper` constructor!
- * @method
- * @memberof Popper
- * @param {Function} callback
- */
- Popper.prototype.onUpdate = function(callback) {
- this.state.updateCallback = callback;
- return this;
- };
-
- /**
- * Helper used to generate poppers from a configuration file
- * @method
- * @memberof Popper
- * @param config {Object} configuration
- * @returns {HTMLElement} popper
- */
- Popper.prototype.parse = function(config) {
- var defaultConfig = {
- tagName: 'div',
- classNames: [ 'popper' ],
- attributes: [],
- parent: root.document.body,
- content: '',
- contentType: 'text',
- arrowTagName: 'div',
- arrowClassNames: [ 'popper__arrow' ],
- arrowAttributes: [ 'x-arrow']
- };
- config = Object.assign({}, defaultConfig, config);
-
- var d = root.document;
-
- var popper = d.createElement(config.tagName);
- addClassNames(popper, config.classNames);
- addAttributes(popper, config.attributes);
- if (config.contentType === 'node') {
- popper.appendChild(config.content.jquery ? config.content[0] : config.content);
- }else if (config.contentType === 'html') {
- popper.innerHTML = config.content;
- } else {
- popper.textContent = config.content;
- }
-
- if (config.arrowTagName) {
- var arrow = d.createElement(config.arrowTagName);
- addClassNames(arrow, config.arrowClassNames);
- addAttributes(arrow, config.arrowAttributes);
- popper.appendChild(arrow);
- }
-
- var parent = config.parent.jquery ? config.parent[0] : config.parent;
-
- // if the given parent is a string, use it to match an element
- // if more than one element is matched, the first one will be used as parent
- // if no elements are matched, the script will throw an error
- if (typeof parent === 'string') {
- parent = d.querySelectorAll(config.parent);
- if (parent.length > 1) {
- console.warn('WARNING: the given `parent` query(' + config.parent + ') matched more than one element, the first one will be used');
- }
- if (parent.length === 0) {
- throw 'ERROR: the given `parent` doesn\'t exists!';
- }
- parent = parent[0];
- }
- // if the given parent is a DOM nodes list or an array of nodes with more than one element,
- // the first one will be used as parent
- if (parent.length > 1 && parent instanceof Element === false) {
- console.warn('WARNING: you have passed as parent a list of elements, the first one will be used');
- parent = parent[0];
- }
-
- // append the generated popper to its parent
- parent.appendChild(popper);
-
- return popper;
-
- /**
- * Adds class names to the given element
- * @function
- * @ignore
- * @param {HTMLElement} target
- * @param {Array} classes
- */
- function addClassNames(element, classNames) {
- classNames.forEach(function(className) {
- element.classList.add(className);
- });
- }
-
- /**
- * Adds attributes to the given element
- * @function
- * @ignore
- * @param {HTMLElement} target
- * @param {Array} attributes
- * @example
- * addAttributes(element, [ 'data-info:foobar' ]);
- */
- function addAttributes(element, attributes) {
- attributes.forEach(function(attribute) {
- element.setAttribute(attribute.split(':')[0], attribute.split(':')[1] || '');
- });
- }
-
- };
-
- /**
- * Helper used to get the position which will be applied to the popper
- * @method
- * @memberof Popper
- * @param config {HTMLElement} popper element
- * @returns {HTMLElement} reference element
- */
- Popper.prototype._getPosition = function(popper, reference) {
- var container = getOffsetParent(reference);
-
- // Decide if the popper will be fixed
- // If the reference element is inside a fixed context, the popper will be fixed as well to allow them to scroll together
- var isParentFixed = isFixed(container);
- return isParentFixed ? 'fixed' : 'absolute';
- };
-
- /**
- * Helper used to determine if the popper's parent is transformed.
- * @param {[type]} popper [description]
- * @return {[type]} [description]
- */
- Popper.prototype._getIsParentTransformed = function(popper) {
- return isTransformed(popper.parentNode);
- };
-
- /**
- * Get offsets to the popper
- * @method
- * @memberof Popper
- * @access private
- * @param {Element} popper - the popper element
- * @param {Element} reference - the reference element (the popper will be relative to this)
- * @returns {Object} An object containing the offsets which will be applied to the popper
- */
- Popper.prototype._getOffsets = function(popper, reference, placement) {
- placement = placement.split('-')[0];
- var popperOffsets = {};
-
- popperOffsets.position = this.state.position;
- var isParentFixed = popperOffsets.position === 'fixed';
-
- var isParentTransformed = this.state.isParentTransformed;
-
- //
- // Get reference element position
- //
- var offsetParent = (isParentFixed && isParentTransformed) ? getOffsetParent(reference) : getOffsetParent(popper);
- var referenceOffsets = getOffsetRectRelativeToCustomParent(reference, offsetParent, isParentFixed, isParentTransformed);
-
- //
- // Get popper sizes
- //
- var popperRect = getOuterSizes(popper);
-
- //
- // Compute offsets of popper
- //
-
- // depending by the popper placement we have to compute its offsets slightly differently
- if (['right', 'left'].indexOf(placement) !== -1) {
- popperOffsets.top = referenceOffsets.top + referenceOffsets.height / 2 - popperRect.height / 2;
- if (placement === 'left') {
- popperOffsets.left = referenceOffsets.left - popperRect.width;
- } else {
- popperOffsets.left = referenceOffsets.right;
- }
- } else {
- popperOffsets.left = referenceOffsets.left + referenceOffsets.width / 2 - popperRect.width / 2;
- if (placement === 'top') {
- popperOffsets.top = referenceOffsets.top - popperRect.height;
- } else {
- popperOffsets.top = referenceOffsets.bottom;
- }
- }
-
- // Add width and height to our offsets object
- popperOffsets.width = popperRect.width;