Merge branch 'MDL-62588-master' of git://github.com/rezaies/moodle
authorDavid Monllao <davidm@moodle.com>
Tue, 19 Jun 2018 10:52:15 +0000 (12:52 +0200)
committerDavid Monllao <davidm@moodle.com>
Tue, 19 Jun 2018 10:52:15 +0000 (12:52 +0200)
77 files changed:
admin/roles/admins.php
admin/tool/dataprivacy/templates/data_requests.mustache
admin/tool/dataprivacy/templates/my_data_requests.mustache
admin/tool/dataprivacy/templates/request_details.mustache
backup/moodle2/tests/restore_stepslib_date_test.php
backup/util/ui/restore_ui_stage.class.php
grade/edit/tree/index.php
lang/en/backup.php
lang/en/mimetypes.php
lib/amd/build/tag.min.js
lib/amd/src/tag.js
lib/classes/filetypes.php
lib/editor/atto/plugins/charmap/styles.css
lib/editor/atto/plugins/charmap/yui/build/moodle-atto_charmap-button/moodle-atto_charmap-button-debug.js
lib/editor/atto/plugins/charmap/yui/build/moodle-atto_charmap-button/moodle-atto_charmap-button-min.js
lib/editor/atto/plugins/charmap/yui/build/moodle-atto_charmap-button/moodle-atto_charmap-button.js
lib/editor/atto/plugins/charmap/yui/src/button/js/button.js
lib/editor/atto/plugins/equation/styles.css
lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button-debug.js
lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button-min.js
lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button.js
lib/editor/atto/plugins/equation/yui/src/button/js/button.js
lib/editor/atto/plugins/image/styles.css
lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button-debug.js
lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button-min.js
lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button.js
lib/editor/atto/plugins/image/yui/src/button/js/button.js
lib/editor/atto/plugins/link/yui/build/moodle-atto_link-button/moodle-atto_link-button-debug.js
lib/editor/atto/plugins/link/yui/build/moodle-atto_link-button/moodle-atto_link-button-min.js
lib/editor/atto/plugins/link/yui/build/moodle-atto_link-button/moodle-atto_link-button.js
lib/editor/atto/plugins/link/yui/src/button/js/button.js
lib/editor/atto/plugins/media/styles.css
lib/editor/atto/plugins/media/yui/build/moodle-atto_media-button/moodle-atto_media-button-debug.js
lib/editor/atto/plugins/media/yui/build/moodle-atto_media-button/moodle-atto_media-button-min.js
lib/editor/atto/plugins/media/yui/build/moodle-atto_media-button/moodle-atto_media-button.js
lib/editor/atto/plugins/media/yui/src/button/js/button.js
lib/editor/atto/plugins/recordrtc/yui/build/moodle-atto_recordrtc-recording/moodle-atto_recordrtc-recording-debug.js
lib/editor/atto/plugins/recordrtc/yui/build/moodle-atto_recordrtc-recording/moodle-atto_recordrtc-recording-min.js
lib/editor/atto/plugins/recordrtc/yui/build/moodle-atto_recordrtc-recording/moodle-atto_recordrtc-recording.js
lib/editor/atto/plugins/recordrtc/yui/src/recording/js/audiomodule.js
lib/editor/atto/plugins/recordrtc/yui/src/recording/js/videomodule.js
lib/editor/atto/plugins/table/styles.css
lib/editor/atto/plugins/table/tests/behat/table.feature
lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button-debug.js
lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button-min.js
lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button.js
lib/editor/atto/plugins/table/yui/src/button/js/button.js
lib/editor/atto/styles.css
message/classes/task/migrate_message_data.php
message/output/popup/amd/build/message_popover_controller.min.js
message/output/popup/amd/build/notification_popover_controller.min.js
message/output/popup/amd/src/message_popover_controller.js
message/output/popup/amd/src/notification_popover_controller.js
message/output/popup/lib.php
message/output/popup/templates/message_popover.mustache
message/output/popup/templates/notification_popover.mustache
message/tests/migrate_message_data_task_test.php
mod/assign/gradingtable.php
mod/assign/tests/locallib_test.php
mod/forum/post.php
tag/classes/privacy/provider.php
tag/tests/privacy_test.php
theme/boost/amd/build/drawer.min.js
theme/boost/amd/src/drawer.js
theme/boost/classes/privacy/provider.php
theme/boost/lang/en/theme_boost.php
theme/boost/scss/moodle/bs4alphacompat.scss
theme/boost/scss/moodle/core.scss
theme/boost/scss/moodle/undo.scss
theme/boost/templates/core/filemanager_fileselect.mustache
theme/boost/templates/core/filemanager_loginform.mustache
theme/boost/templates/core/filemanager_selectlayout.mustache
theme/boost/templates/core/filemanager_uploadform.mustache
theme/boost/tests/privacy_test.php [new file with mode: 0644]
theme/bootstrapbase/less/moodle/bs4-compat.less
theme/bootstrapbase/less/moodle/forms.less
theme/bootstrapbase/style/moodle.css

index 8245949..4b341b3 100644 (file)
@@ -80,9 +80,16 @@ if (optional_param('add', false, PARAM_BOOL) and confirm_sesskey()) {
         }
 
         if (isset($admins[$newmain])) {
+            $logstringold = implode(', ', $admins);
+
             unset($admins[$newmain]);
             array_unshift($admins, $newmain);
+
+            $logstringnew = implode(', ', $admins);
+
             set_config('siteadmins', implode(',', $admins));
+            add_to_config_log('siteadmins', $logstringold, $logstringnew, null);
+
             redirect($PAGE->url);
         }
     }
@@ -95,8 +102,16 @@ if (optional_param('add', false, PARAM_BOOL) and confirm_sesskey()) {
             $admins[$admin] = $admin;
         }
     }
+
+    $logstringold = implode(', ', $admins);
+
     $admins[$confirmadd] = $confirmadd;
+
+    $logstringnew = implode(', ', $admins);
+
     set_config('siteadmins', implode(',', $admins));
+    add_to_config_log('siteadmins', $logstringold, $logstringnew, 'core');
+
     redirect($PAGE->url);
 
 } else if ($confirmdel and confirm_sesskey() and $confirmdel != $USER->id) {
@@ -107,8 +122,16 @@ if (optional_param('add', false, PARAM_BOOL) and confirm_sesskey()) {
             $admins[$admin] = $admin;
         }
     }
+
+    $logstringold = implode(', ', $admins);
+
     unset($admins[$confirmdel]);
+
+    $logstringnew = implode(', ', $admins);
+
     set_config('siteadmins', implode(',', $admins));
+    add_to_config_log('siteadmins', $logstringold, $logstringnew, 'core');
+
     redirect($PAGE->url);
 }
 
index beed5ac..93c9a8c 100644 (file)
               }}>
                 <td>{{typenameshort}}</td>
                 <td><a href="{{foruser.profileurl}}" title="{{#str}}viewprofile{{/str}}">{{foruser.fullname}}</a></td>
-                <td>{{#userdate}} {{timecreated}}, {{#str}} strftimedate {{/str}} {{/userdate}}</td>
+                <td>{{#userdate}} {{timecreated}}, {{#str}} strftimedatetime {{/str}} {{/userdate}}</td>
                 <td>
                     <span class="label {{statuslabelclass}}">{{statuslabel}}</span>
                 </td>
index 1bdcbdb..6cc39e1 100644 (file)
               }} data-status="{{status}}"{{!
               }}>
                 <td>{{typename}}</td>
-                <td>{{#userdate}} {{timecreated}}, {{#str}} strftimedate {{/str}} {{/userdate}}</td>
+                <td>{{#userdate}} {{timecreated}}, {{#str}} strftimedatetime {{/str}} {{/userdate}}</td>
                 <td>
                     <span class="label {{statuslabelclass}}">{{statuslabel}}</span>
                 </td>
index 531e394..afa5c48 100644 (file)
@@ -63,7 +63,7 @@
             <a href="mailto:{{foruser.email}}">{{foruser.email}}</a>
             <div class="clearfix m-t-1 m-b-1">
             <span class="pull-left m-r-1">
-                <strong>{{#str}}daterequesteddetail, tool_dataprivacy{{/str}}</strong> {{#userdate}} {{timecreated}}, {{#str}} strftimedate {{/str}} {{/userdate}}
+                <strong>{{#str}}daterequesteddetail, tool_dataprivacy{{/str}}</strong> {{#userdate}} {{timecreated}}, {{#str}} strftimedatetime {{/str}} {{/userdate}}
             </span>
                 <span class="pull-left m-r-1">
                 <strong>{{#str}}statusdetail, tool_dataprivacy{{/str}}</strong>
index 1bcce5f..e5cc3f4 100644 (file)
@@ -244,7 +244,7 @@ class restore_stepslib_date_testcase extends restore_date_testcase {
         // Testing the restore of an overridden grade.
         list($course, $assign) = $this->create_course_and_module('assign', []);
         $cm = $DB->get_record('course_modules', ['course' => $course->id, 'instance' => $assign->id]);
-        $assignobj = new testable_assign(context_module::instance($cm->id), $cm, $course);
+        $assignobj = new mod_assign_testable_assign(context_module::instance($cm->id), $cm, $course);
         $submission = $assignobj->get_user_submission($USER->id, true);
         $grade = $assignobj->get_user_grade($USER->id, true);
         $grade->grade = 75;
@@ -300,7 +300,7 @@ class restore_stepslib_date_testcase extends restore_date_testcase {
                 'completionusegrade' => 1 // Student must receive a grade to complete this activity.
             ]);
         $cm = $DB->get_record('course_modules', ['course' => $course->id, 'instance' => $assign->id]);
-        $assignobj = new testable_assign(context_module::instance($cm->id), $cm, $course);
+        $assignobj = new mod_assign_testable_assign(context_module::instance($cm->id), $cm, $course);
         $submission = $assignobj->get_user_submission($USER->id, true);
         $grade = $assignobj->get_user_grade($USER->id, true);
         $grade->grade = 75;
@@ -410,4 +410,4 @@ class restore_stepslib_date_testcase extends restore_date_testcase {
             $this->assertEquals($dates['originaldate'], $dates['restoredate']);
         }
     }
-}
\ No newline at end of file
+}
index 2ff89e6..bc09bc5 100644 (file)
@@ -1061,7 +1061,26 @@ class restore_ui_stage_process extends restore_ui_stage {
                 if (!empty($info->role_mappings->mappings)) {
                     $context = context_course::instance($this->ui->get_controller()->get_courseid());
                     $assignableroles = get_assignable_roles($context, ROLENAME_ALIAS, false);
-                    $html .= $renderer->role_mappings($info->role_mappings->mappings, $assignableroles);
+
+                    // Get current role mappings.
+                    $currentroles = role_fix_names(get_all_roles(), $context);
+                    // Get backup role mappings.
+                    $rolemappings = $info->role_mappings->mappings;
+
+                    array_map(function($rolemapping) use ($currentroles) {
+                        foreach ($currentroles as $role) {
+                            // Find matching archetype to determine the backup's shortname for label display.
+                            if ($rolemapping->archetype == $role->archetype) {
+                                $rolemapping->name = $rolemapping->shortname;
+                                break;
+                            }
+                        }
+                        if ($rolemapping->name == null) {
+                            $rolemapping->name = get_string('undefinedrolemapping', 'backup', $rolemapping->archetype);
+                        }
+                    }, $rolemappings);
+
+                    $html .= $renderer->role_mappings($rolemappings, $assignableroles);
                 }
                 break;
             default:
index 3a1ce5e..b898b99 100644 (file)
@@ -274,13 +274,13 @@ echo $OUTPUT->container_start('buttons mdl-align');
 if ($moving) {
     echo $OUTPUT->single_button(new moodle_url('index.php', array('id'=>$course->id)), get_string('cancel'), 'get');
 } else {
-    echo $OUTPUT->single_button(new moodle_url('category.php', array('courseid'=>$course->id)), get_string('addcategory', 'grades'), 'get');
-    echo $OUTPUT->single_button(new moodle_url('item.php', array('courseid'=>$course->id)), get_string('additem', 'grades'), 'get');
-
+    echo $OUTPUT->single_button(new moodle_url('item.php', array('courseid' => $course->id)), get_string('additem',
+        'grades'), 'get');
     if (!empty($CFG->enableoutcomes)) {
         echo $OUTPUT->single_button(new moodle_url('outcomeitem.php', array('courseid'=>$course->id)), get_string('addoutcomeitem', 'grades'), 'get');
     }
-
+    echo $OUTPUT->single_button(new moodle_url('category.php', array('courseid' => $course->id)), get_string('addcategory',
+        'grades'), 'get');
     //echo $OUTPUT->(new moodle_url('index.php', array('id'=>$course->id, 'action'=>'autosort')), get_string('autosort', 'grades'), 'get');
 }
 
index dc711e8..abaf88e 100644 (file)
@@ -326,6 +326,7 @@ $string['timetaken'] = 'Time taken';
 $string['title'] = 'Title';
 $string['totalcategorysearchresults'] = 'Total categories: {$a}';
 $string['totalcoursesearchresults'] = 'Total courses: {$a}';
+$string['undefinedrolemapping'] = 'Role mapping undefined for: \'{$a}\' archetype';
 $string['unnamedsection'] = 'Unnamed section';
 $string['userinfo'] = 'Userinfo';
 $string['module'] = 'Module';
index 3889226..15b8463 100644 (file)
@@ -36,6 +36,7 @@
  */
 
 $string['application/epub_zip'] = 'EPUB ebook';
+$string['application/json'] = '{$a->MIMETYPE2} text';
 $string['application/msword'] = 'Word document';
 $string['application/pdf'] = 'PDF document';
 $string['application/vnd.moodle.backup'] = 'Moodle backup';
index ab06031..fd51f0b 100644 (file)
Binary files a/lib/amd/build/tag.min.js and b/lib/amd/build/tag.min.js differ
index 1f1d3fb..1609564 100644 (file)
@@ -150,8 +150,8 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
                 ]).done(function(s) {
                     var el = $('<div><form id="combinetags_form" class="form-inline">' +
                         '<p class="description"></p><p class="options"></p>' +
-                        '<p class="mdl-align"><input type="submit" id="combinetags_submit"/>' +
-                        '<input type="button" id="combinetags_cancel"/></p>' +
+                        '<p class="mdl-align"><input type="submit" class="btn btn-primary" id="combinetags_submit"/>' +
+                        '<input type="button" class="btn btn-secondary" id="combinetags_cancel"/></p>' +
                         '</form></div>');
                     el.find('.description').html(s[1]);
                     el.find('#combinetags_submit').attr('value', s[2]);
@@ -223,8 +223,8 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
                         '<input type="hidden" name="sesskey" value="' + M.cfg.sesskey + '"/>' +
                         '<p><label for="id_tagslist">' + s[1] + '</label>' +
                         '<input type="text" id="id_tagslist" name="tagslist"/></p>' +
-                        '<p class="mdl-align"><input type="submit" id="addtags_submit"/>' +
-                        '<input type="button" id="addtags_cancel"/></p>' +
+                        '<p class="mdl-align"><input type="submit" class="btn btn-primary" id="addtags_submit"/>' +
+                        '<input type="button" class="btn btn-secondary" id="addtags_cancel"/></p>' +
                         '</form></div>');
                     el.find('#addtags_form').attr('action', window.location.href);
                     el.find('#addtags_submit').attr('value', s[2]);
@@ -295,8 +295,8 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
                             '<input id="addtagcoll_name" type="text"/></p>' +
                             '<p><label for="addtagcoll_searchable"></label>: ' +
                             '<input id="addtagcoll_searchable" type="checkbox" value="1" checked/></p>' +
-                            '<p class="mdl-align"><input type="submit" id="addtagcoll_submit"/>' +
-                            '<input type="button" id="addtagcoll_cancel"/></p>' +
+                            '<p class="mdl-align"><input type="submit" class="btn btn-primary" id="addtagcoll_submit"/>' +
+                            '<input type="button" class="btn btn-secondary" id="addtagcoll_cancel"/></p>' +
                             '</form></div>');
                         el.find('label[for="addtagcoll_name"]').html(s[1]);
                         el.find('label[for="addtagcoll_searchable"]').html(s[2]);
index 23c0191..4a84e55 100644 (file)
@@ -139,6 +139,7 @@ abstract class core_filetypes {
             'jpg' => array('type' => 'image/jpeg', 'icon' => 'jpeg', 'groups' => array('image', 'web_image'), 'string' => 'image'),
             'jqz' => array('type' => 'text/xml', 'icon' => 'markup'),
             'js' => array('type' => 'application/x-javascript', 'icon' => 'text', 'groups' => array('web_file')),
+            'json' => array('type' => 'application/json', 'icon' => 'text'),
             'latex' => array('type' => 'application/x-latex', 'icon' => 'text'),
             'm' => array('type' => 'text/plain', 'icon' => 'sourcecode'),
             'mbz' => array('type' => 'application/vnd.moodle.backup', 'icon' => 'moodle'),
index 0f151ec..4656462 100644 (file)
@@ -1,4 +1,4 @@
 .atto_charmap_selector button {
-    width: 2em;
-    padding: 0 3px;
+    width: 2.18rem;
+    margin: 0.1rem;
 }
index 30e0e37..422e2d8 100644 (file)
Binary files a/lib/editor/atto/plugins/charmap/yui/build/moodle-atto_charmap-button/moodle-atto_charmap-button-debug.js and b/lib/editor/atto/plugins/charmap/yui/build/moodle-atto_charmap-button/moodle-atto_charmap-button-debug.js differ
index 77b7449..339dad4 100644 (file)
Binary files a/lib/editor/atto/plugins/charmap/yui/build/moodle-atto_charmap-button/moodle-atto_charmap-button-min.js and b/lib/editor/atto/plugins/charmap/yui/build/moodle-atto_charmap-button/moodle-atto_charmap-button-min.js differ
index 30e0e37..422e2d8 100644 (file)
Binary files a/lib/editor/atto/plugins/charmap/yui/build/moodle-atto_charmap-button/moodle-atto_charmap-button.js and b/lib/editor/atto/plugins/charmap/yui/build/moodle-atto_charmap-button/moodle-atto_charmap-button.js differ
index 6f549b4..397f1fe 100644 (file)
@@ -377,7 +377,7 @@ Y.namespace('M.atto_charmap').Button = Y.Base.create('button', Y.M.editor_atto.E
             '<div class="{{CSS.CHARMAP}}">' +
                 '{{#each CHARMAP}}' +
                     '{{#if this.[2]}}' +
-                    '<button class="{{../../CSS.BUTTON}}" ' +
+                    '<button class="btn btn-default btn-sm {{../../CSS.BUTTON}}" ' +
                         'aria-label="{{get_string this.[3] ../../component}}" ' +
                         'title="{{get_string this.[3] ../../component}}" ' +
                         'data-character="{{this.[0]}}" ' +
index f6081a0..8df2d6b 100644 (file)
@@ -1,16 +1,3 @@
-.atto_equation_library .yui3-tabview-list {
-    border: none;
-}
-
-.atto_equation_library .yui3-tab-selected .yui3-tab-label,
-.yui3-skin-sam #atto_equation_library .yui3-tab-selected .yui3-tab-label:focus,
-.yui3-skin-sam #atto_equation_library .yui3-tab-selected .yui3-tab-label:hover {
-    background: none;
-    color: black;
-    border-top-left-radius: 4px;
-    border-top-right-radius: 4px;
-}
-
 .atto_equation_library button {
     margin: 0.25%;
     min-width: 12%;
index ae1d92c..fdc94ce 100644 (file)
Binary files a/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button-debug.js and b/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button-debug.js differ
index a5ff287..00d0781 100644 (file)
Binary files a/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button-min.js and b/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button-min.js differ
index f98b58c..1274071 100644 (file)
Binary files a/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button.js and b/lib/editor/atto/plugins/equation/yui/build/moodle-atto_equation-button/moodle-atto_equation-button.js differ
index 849a967..6db2cb8 100644 (file)
@@ -60,29 +60,34 @@ var COMPONENTNAME = 'atto_equation',
                 '<textarea class="fullwidth {{CSS.EQUATION_TEXT}}" ' +
                         'id="{{elementid}}_{{CSS.EQUATION_TEXT}}" rows="8"></textarea><br/>' +
                 '<label for="{{elementid}}_{{CSS.EQUATION_PREVIEW}}">{{get_string "preview" component}}</label>' +
-                '<div describedby="{{elementid}}_cursorinfo" class="well well-small fullwidth {{CSS.EQUATION_PREVIEW}}" ' +
+                '<div describedby="{{elementid}}_cursorinfo" class="well well-small p-1 fullwidth {{CSS.EQUATION_PREVIEW}}" ' +
                         'id="{{elementid}}_{{CSS.EQUATION_PREVIEW}}"></div>' +
                 '<div id="{{elementid}}_cursorinfo">{{get_string "cursorinfo" component}}</div>' +
                 '<div class="mdl-align">' +
                     '<br/>' +
-                    '<button class="{{CSS.SUBMIT}}">{{get_string "saveequation" component}}</button>' +
+                    '<button class="btn btn-default {{CSS.SUBMIT}}">{{get_string "saveequation" component}}</button>' +
                 '</div>' +
             '</form>',
         LIBRARY: '' +
             '<div class="{{CSS.LIBRARY}}">' +
-                '<ul>' +
+                '<ul class="root nav nav-tabs m-b-1" role="tablist">' +
                     '{{#each library}}' +
-                        '<li><a href="#{{../elementid}}_{{../CSS.LIBRARY_GROUP_PREFIX}}_{{@key}}">' +
-                            '{{get_string groupname ../component}}' +
-                        '</a></li>' +
+                        '<li  class="nav-item">' +
+                            '<a class="nav-link" href="#{{../elementid}}_{{../CSS.LIBRARY_GROUP_PREFIX}}_{{@key}}" ' +
+                                ' role="tab" data-toggle="tab">' +
+                                '{{get_string groupname ../component}}' +
+                            '</a>' +
+                        '</li>' +
                     '{{/each}}' +
                 '</ul>' +
-                '<div class="{{CSS.LIBRARY_GROUPS}}">' +
+                '<div class="tab-content m-b-1 {{CSS.LIBRARY_GROUPS}}">' +
                     '{{#each library}}' +
-                        '<div id="{{../elementid}}_{{../CSS.LIBRARY_GROUP_PREFIX}}_{{@key}}">' +
+                        '<div data-medium-type="{{CSS.LINK}}" class="tab-pane" ' +
+                        'id="{{../elementid}}_{{../CSS.LIBRARY_GROUP_PREFIX}}_{{@key}}">' +
                             '<div role="toolbar">' +
                             '{{#split "\n" elements}}' +
-                                '<button tabindex="-1" data-tex="{{this}}" aria-label="{{this}}" title="{{this}}">' +
+                                '<button class="btn btn-default" tabindex="-1" data-tex="{{this}}"' +
+                                    'aria-label="{{this}}" title="{{this}}">' +
                                     '{{../../DELIMITERS.START}}{{this}}{{../../DELIMITERS.END}}' +
                                 '</button>' +
                             '{{/split}}' +
@@ -220,13 +225,8 @@ Y.namespace('M.atto_equation').Button = Y.Base.create('button', Y.M.editor_atto.
         var content = this._getDialogueContent();
         dialogue.set('bodyContent', content);
 
-        var library = content.one(SELECTORS.LIBRARY);
+        content.one('.nav-item:first-child .nav-link').getDOMNode().click();
 
-        var tabview = new Y.TabView({
-            srcNode: library
-        });
-
-        tabview.render();
         dialogue.show();
         // Notify the filters about the modified nodes.
         require(['core/event'], function(event) {
index a913c73..8656f0e 100644 (file)
@@ -6,7 +6,7 @@
 }
 
 .atto_image_preview_box {
-    max-height: 200px;
+    max-height: 150px;
     margin-bottom: 1em;
     overflow: auto;
 }
     cursor: pointer;
 }
 
-.atto_image_size {
-    display: inline-block;
-}
-
-.atto_image_size input[type=checkbox] {
-    margin-left: 1em;
-    margin-right: 1em;
-}
-
-.atto_image_size input[type=text] {
-    width: 3em;
-}
-
-.atto_image_size label {
-    display: inline-block;
-}
-
 .atto_image_button_text-top {
     vertical-align: text-top;
     margin: 0 0.5em;
index 69ab2fd..899c1a8 100644 (file)
Binary files a/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button-debug.js and b/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button-debug.js differ
index 78edf53..bbe3e39 100644 (file)
Binary files a/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button-min.js and b/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button-min.js differ
index 18416c3..293794c 100644 (file)
Binary files a/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button.js and b/lib/editor/atto/plugins/image/yui/build/moodle-atto_image-button/moodle-atto_image-button.js differ
index f9c0d60..5cc1626 100644 (file)
@@ -94,52 +94,79 @@ var CSS = {
 
     TEMPLATE = '' +
             '<form class="atto_form">' +
-                '<label for="{{elementid}}_{{CSS.INPUTURL}}">{{get_string "enterurl" component}}</label>' +
-                '<input class="fullwidth {{CSS.INPUTURL}}" type="url" id="{{elementid}}_{{CSS.INPUTURL}}" size="32"/>' +
-                '<br/>' +
 
                 // Add the repository browser button.
                 '{{#if showFilepicker}}' +
-                    '<button class="{{CSS.IMAGEBROWSER}}" type="button">{{get_string "browserepositories" component}}</button>' +
+                    '<div class="m-b-1">' +
+                        '<label for="{{elementid}}_{{CSS.INPUTURL}}">{{get_string "enterurl" component}}</label>' +
+                        '<div class="input-group input-append w-100">' +
+                            '<input class="form-control {{CSS.INPUTURL}}" type="url" ' +
+                            'id="{{elementid}}_{{CSS.INPUTURL}}" size="32"/>' +
+                            '<span class="input-group-append">' +
+                                '<button class="btn btn-default {{CSS.IMAGEBROWSER}}" type="button">' +
+                                '{{get_string "browserepositories" component}}</button>' +
+                            '</span>' +
+                        '</div>' +
+                    '</div>' +
+                '{{else}}' +
+                    '<div class="m-b-1">' +
+                        '<label for="{{elementid}}_{{CSS.INPUTURL}}">{{get_string "enterurl" component}}</label>' +
+                        '<input class="form-control fullwidth {{CSS.INPUTURL}}" type="url" ' +
+                        'id="{{elementid}}_{{CSS.INPUTURL}}" size="32"/>' +
+                    '</div>' +
                 '{{/if}}' +
 
                 // Add the Alt box.
-                '<div style="display:none" role="alert" class="warning {{CSS.IMAGEALTWARNING}}">' +
+                '<div style="display:none" role="alert" class="alert alert-warning m-b-1 {{CSS.IMAGEALTWARNING}}">' +
                     '{{get_string "presentationoraltrequired" component}}' +
                 '</div>' +
+                '<div class="m-b-1">' +
                 '<label for="{{elementid}}_{{CSS.INPUTALT}}">{{get_string "enteralt" component}}</label>' +
-                '<input class="fullwidth {{CSS.INPUTALT}}" type="text" value="" id="{{elementid}}_{{CSS.INPUTALT}}" size="32"/>' +
-                '<br/>' +
+                '<input class="form-control fullwidth {{CSS.INPUTALT}}" type="text" value="" ' +
+                'id="{{elementid}}_{{CSS.INPUTALT}}" size="32"/>' +
 
                 // Add the presentation select box.
-                '<input type="checkbox" class="{{CSS.IMAGEPRESENTATION}}" id="{{elementid}}_{{CSS.IMAGEPRESENTATION}}"/>' +
-                '<label class="sameline" for="{{elementid}}_{{CSS.IMAGEPRESENTATION}}">' +
+                '<div class="form-check">' +
+                '<input type="checkbox" class="form-check-input {{CSS.IMAGEPRESENTATION}}" ' +
+                    'id="{{elementid}}_{{CSS.IMAGEPRESENTATION}}"/>' +
+                '<label class="form-check-label" for="{{elementid}}_{{CSS.IMAGEPRESENTATION}}">' +
                     '{{get_string "presentation" component}}' +
                 '</label>' +
-                '<br/>' +
+                '</div>' +
+                '</div>' +
 
                 // Add the size entry boxes.
-                '<label class="sameline" for="{{elementid}}_{{CSS.INPUTSIZE}}">{{get_string "size" component}}</label>' +
-                '<div id="{{elementid}}_{{CSS.INPUTSIZE}}" class="{{CSS.INPUTSIZE}}">' +
+                '<div class="m-b-1">' +
+                '<label class="" for="{{elementid}}_{{CSS.INPUTSIZE}}">{{get_string "size" component}}</label>' +
+                '<div id="{{elementid}}_{{CSS.INPUTSIZE}}" class="form-inline {{CSS.INPUTSIZE}}">' +
                 '<label class="accesshide" for="{{elementid}}_{{CSS.INPUTWIDTH}}">{{get_string "width" component}}</label>' +
-                '<input type="text" class="{{CSS.INPUTWIDTH}} input-mini" id="{{elementid}}_{{CSS.INPUTWIDTH}}" size="4"/> x ' +
+                '<input type="text" class="form-control m-r-1 input-mini {{CSS.INPUTWIDTH}}" ' +
+                'id="{{elementid}}_{{CSS.INPUTWIDTH}}" size="4"/> x' +
 
                 // Add the height entry box.
                 '<label class="accesshide" for="{{elementid}}_{{CSS.INPUTHEIGHT}}">{{get_string "height" component}}</label>' +
-                '<input type="text" class="{{CSS.INPUTHEIGHT}} input-mini" id="{{elementid}}_{{CSS.INPUTHEIGHT}}" size="4"/>' +
+                '<input type="text" class="form-control m-l-1 input-mini {{CSS.INPUTHEIGHT}}" ' +
+                'id="{{elementid}}_{{CSS.INPUTHEIGHT}}" size="4"/>' +
 
                 // Add the constrain checkbox.
-                '<input type="checkbox" class="{{CSS.INPUTCONSTRAIN}} sameline" id="{{elementid}}_{{CSS.INPUTCONSTRAIN}}"/>' +
-                '<label for="{{elementid}}_{{CSS.INPUTCONSTRAIN}}">{{get_string "constrain" component}}</label>' +
+                '<div class="form-check m-l-2">' +
+                '<input type="checkbox" class="form-check-input {{CSS.INPUTCONSTRAIN}}" ' +
+                'id="{{elementid}}_{{CSS.INPUTCONSTRAIN}}"/>' +
+                '<label class="form-check-label" for="{{elementid}}_{{CSS.INPUTCONSTRAIN}}">' +
+                '{{get_string "constrain" component}}</label>' +
+                '</div>' +
+                '</div>' +
                 '</div>' +
 
                 // Add the alignment selector.
-                '<label class="sameline" for="{{elementid}}_{{CSS.INPUTALIGNMENT}}">{{get_string "alignment" component}}</label>' +
-                '<select class="{{CSS.INPUTALIGNMENT}}" id="{{elementid}}_{{CSS.INPUTALIGNMENT}}">' +
+                '<div class="form-inline m-b-1">' +
+                '<label class="for="{{elementid}}_{{CSS.INPUTALIGNMENT}}">{{get_string "alignment" component}}</label>' +
+                '<select class="custom-select {{CSS.INPUTALIGNMENT}}" id="{{elementid}}_{{CSS.INPUTALIGNMENT}}">' +
                     '{{#each alignments}}' +
                         '<option value="{{value}}">{{get_string str ../component}}</option>' +
                     '{{/each}}' +
                 '</select>' +
+                '</div>' +
                 // Hidden input to store custom styles.
                 '<input type="hidden" class="{{CSS.INPUTCUSTOMSTYLE}}"/>' +
                 '<br/>' +
@@ -151,7 +178,7 @@ var CSS = {
                 '</div>' +
 
                 // Add the submit button and close the form.
-                '<button class="{{CSS.INPUTSUBMIT}}" type="submit">{{get_string "saveimage" component}}</button>' +
+                '<button class="btn btn-default {{CSS.INPUTSUBMIT}}" type="submit">{{get_string "saveimage" component}}</button>' +
                 '</div>' +
             '</form>',
 
index 7aa1907..d1c971e 100644 (file)
Binary files a/lib/editor/atto/plugins/link/yui/build/moodle-atto_link-button/moodle-atto_link-button-debug.js and b/lib/editor/atto/plugins/link/yui/build/moodle-atto_link-button/moodle-atto_link-button-debug.js differ
index f7b3aeb..4f1d046 100644 (file)
Binary files a/lib/editor/atto/plugins/link/yui/build/moodle-atto_link-button/moodle-atto_link-button-min.js and b/lib/editor/atto/plugins/link/yui/build/moodle-atto_link-button/moodle-atto_link-button-min.js differ
index 7aa1907..d1c971e 100644 (file)
Binary files a/lib/editor/atto/plugins/link/yui/build/moodle-atto_link-button/moodle-atto_link-button.js and b/lib/editor/atto/plugins/link/yui/build/moodle-atto_link-button/moodle-atto_link-button.js differ
index 8226483..51112dd 100644 (file)
@@ -41,20 +41,32 @@ var COMPONENTNAME = 'atto_link',
     },
     TEMPLATE = '' +
             '<form class="atto_form">' +
-                '<label for="{{elementid}}_atto_link_urlentry">{{get_string "enterurl" component}}</label>' +
-                '<input class="fullwidth url {{CSS.URLINPUT}}" type="url" id="{{elementid}}_atto_link_urlentry" size="32"/><br/>' +
-
-                // Add the repository browser button.
                 '{{#if showFilepicker}}' +
-                    '<button class="openlinkbrowser">{{get_string "browserepositories" component}}</button>' +
-                    '<br/>' +
+                    '<label for="{{elementid}}_atto_link_urlentry">{{get_string "enterurl" component}}</label>' +
+                    '<div class="input-group input-append w-100 m-b-1">' +
+                        '<input class="form-control url {{CSS.URLINPUT}}" type="url" ' +
+                        'id="{{elementid}}_atto_link_urlentry"/>' +
+                        '<span class="input-group-append">' +
+                            '<button class="btn btn-default openlinkbrowser" type="button">' +
+                            '{{get_string "browserepositories" component}}</button>' +
+                        '</span>' +
+                    '</div>' +
+                '{{else}}' +
+                    '<div class="m-b-1">' +
+                        '<label for="{{elementid}}_atto_link_urlentry">{{get_string "enterurl" component}}</label>' +
+                        '<input class="form-control fullwidth url {{CSS.URLINPUT}}" type="url" ' +
+                        'id="{{elementid}}_atto_link_urlentry" size="32"/>' +
+                    '</div>' +
                 '{{/if}}' +
-                '<input type="checkbox" class="newwindow" id="{{elementid}}_{{CSS.NEWWINDOW}}"/>' +
-                '<label class="sameline" for="{{elementid}}_{{CSS.NEWWINDOW}}">{{get_string "openinnewwindow" component}}</label>' +
-                '<br/>' +
+                '<div class="form-check">' +
+                    '<input type="checkbox" class="form-check-input newwindow" id="{{elementid}}_{{CSS.NEWWINDOW}}"/>' +
+                    '<label class="form-check-label" for="{{elementid}}_{{CSS.NEWWINDOW}}">' +
+                    '{{get_string "openinnewwindow" component}}' +
+                    '</label>' +
+                '</div>' +
                 '<div class="mdl-align">' +
                     '<br/>' +
-                    '<button type="submit" class="submit">{{get_string "createlink" component}}</button>' +
+                    '<button type="submit" class="btn btn-default submit">{{get_string "createlink" component}}</button>' +
                 '</div>' +
             '</form>';
 Y.namespace('M.atto_link').Button = Y.Base.create('button', Y.M.editor_atto.EditorPlugin, [], {
index ee5a759..f1ecb10 100644 (file)
@@ -1,106 +1,4 @@
-.atto_form.atto_media #video input,
-.atto_form.atto_media #audio input,
-.atto_form.atto_media #link input {
-    box-sizing: border-box;
-    height: inherit;
-}
-
 .atto_form.atto_media > .tab-content {
     max-height: 45vh;
     overflow-x: hidden;
-    padding-left: 20px;
-    padding-right: 20px;
-    margin-left: -20px;
-    margin-right: -21px;
-}
-
-.atto_form.atto_media [id$="-advanced-settings"] label {
-    margin-right: 10px;
-}
-
-.atto_form.atto_media label {
-    display: inline-block;
-}
-
-.atto_form.atto_media label > span {
-    display: inline-block;
-    min-width: 6em;
-}
-
-.atto_form.atto_media .atto_media_track_lang_entry,
-.atto_form.atto_media .atto_media_track_label_entry {
-    width: 168px;
-}
-
-.atto_form.atto_media .atto_media_track_source {
-    margin-bottom: 10px;
-}
-
-.atto_form.atto_media select {
-    margin-right: 10px;
-}
-
-.atto_form.atto_media [id$="-tracks"] input[type=checkbox] {
-    margin-left: 10px;
-}
-
-.atto_form.atto_media .atto_media_track ~ .atto_media_track {
-    margin-top: 5px;
-    padding-top: 10px;
-    border-top: 1px solid #e5e5e5;
-}
-
-.atto_form.atto_media label.fullwidth {
-    width: 100%;
-}
-
-.atto_media_postersize {
-    display: inline-block;
-}
-
-.atto_media_postersize input[type=text] {
-    width: 3em;
-}
-
-input[size].atto_media_url_entry {
-    width: calc(100% - 15px);
-}
-
-.openmediabrowser {
-    margin-top: -4px;
-}
-
-.addcomponent,
-.removecomponent {
-    font-weight: bold;
-    margin-right: 10px;
-}
-
-.trackhelp {
-    text-align: right;
-}
-
-.atto_form.atto_media .atto_media_source > label {
-    width: calc(100% - 153px);
-}
-
-.atto_form.atto_media .atto_media_track_lang_entry,
-.atto_form.atto_media .atto_media_track_label_entry {
-    width: 116px;
-}
-
-.langlabel {
-    width: 42%;
-}
-
-.labellabel {
-    width: 44%;
-}
-
-.defaultlabel {
-    width: 14%;
-}
-
-[data-medium-type=link] label {
-    width: 100%;
-}
+}
\ No newline at end of file
index 603896a..541685a 100644 (file)
Binary files a/lib/editor/atto/plugins/media/yui/build/moodle-atto_media-button/moodle-atto_media-button-debug.js and b/lib/editor/atto/plugins/media/yui/build/moodle-atto_media-button/moodle-atto_media-button-debug.js differ
index 0049c93..cfdd7c1 100644 (file)
Binary files a/lib/editor/atto/plugins/media/yui/build/moodle-atto_media-button/moodle-atto_media-button-min.js and b/lib/editor/atto/plugins/media/yui/build/moodle-atto_media-button/moodle-atto_media-button-min.js differ
index 603896a..541685a 100644 (file)
Binary files a/lib/editor/atto/plugins/media/yui/build/moodle-atto_media-button/moodle-atto_media-button.js and b/lib/editor/atto/plugins/media/yui/build/moodle-atto_media-button/moodle-atto_media-button.js differ
index f5a63c0..b406076 100644 (file)
@@ -114,7 +114,7 @@ var COMPONENTNAME = 'atto_media',
     TEMPLATES = {
         ROOT: '' +
             '<form class="mform atto_form atto_media" id="{{elementid}}_atto_media_form">' +
-                '<ul class="root nav nav-tabs" role="tablist">' +
+                '<ul class="root nav nav-tabs m-b-1" role="tablist">' +
                     '<li data-medium-type="{{CSS.LINK}}" class="nav-item">' +
                         '<a class="nav-link active" href="#{{elementid}}_{{CSS.LINK}}" role="tab" data-toggle="tab">' +
                             '{{get_string "link" component}}' +
@@ -144,17 +144,15 @@ var COMPONENTNAME = 'atto_media',
                 '</div>' +
                 '<div class="mdl-align">' +
                     '<br/>' +
-                    '<button class="submit" type="submit">{{get_string "createmedia" component}}</button>' +
+                    '<button class="btn btn-default submit" type="submit">{{get_string "createmedia" component}}</button>' +
                 '</div>' +
             '</form>',
         TAB_PANES: {
             LINK: '' +
                 '{{renderPartial "form_components.source" context=this id=CSS.LINK_SOURCE}}' +
-                '<label>' +
-                    'Enter name' +
-                    '<input class="fullwidth {{CSS.NAME_INPUT}}" type="text" id="{{elementid}}_link_nameentry"' +
-                        'size="32" required="true"/>' +
-                '</label>',
+                '<label for="{{elementid}}_link_nameentry">{{get_string "entername" component}}</label>' +
+                '<input class="form-control fullwidth {{CSS.NAME_INPUT}}" type="text" id="{{elementid}}_link_nameentry"' +
+                        'size="32" required="true"/>',
             VIDEO: '' +
                 '{{renderPartial "form_components.source" context=this id=CSS.MEDIA_SOURCE entersourcelabel="videosourcelabel"' +
                     ' addcomponentlabel="addsource" multisource="true" addsourcehelp=helpStrings.addsource}}' +
@@ -200,13 +198,19 @@ var COMPONENTNAME = 'atto_media',
         FORM_COMPONENTS: {
             SOURCE: '' +
                 '<div class="{{CSS.SOURCE}} {{id}}">' +
-                    '<label>' +
+                    '<div class="m-b-1">' +
+                        '<label for="url-input">' +
                         '{{#entersourcelabel}}{{get_string ../entersourcelabel ../component}}{{/entersourcelabel}}' +
-                        '{{^entersourcelabel}}{{get_string "entersource" ../component}}{{/entersourcelabel}}</a>' +
-                        '<br/>' +
-                        '<input class="{{CSS.URL_INPUT}}" type="url" size="32"/>' +
-                    '</label>' +
-                    '<button class="openmediabrowser" type="button">{{get_string "browserepositories" component}}</button>' +
+                        '{{^entersourcelabel}}{{get_string "entersource" ../component}}{{/entersourcelabel}}' +
+                        '</label>' +
+                        '<div class="input-group input-append w-100">' +
+                            '<input id="url-input" class="form-control {{CSS.URL_INPUT}}" type="url" size="32"/>' +
+                            '<span class="input-group-append">' +
+                                '<button class="btn btn-default openmediabrowser" type="button">' +
+                                '{{get_string "browserepositories" component}}</button>' +
+                            '</span>' +
+                        '</div>' +
+                    '</div>' +
                     '{{#multisource}}' +
                         '{{renderPartial "form_components.add_component" context=../this label=../addcomponentlabel ' +
                             ' help=../addsourcehelp}}' +
@@ -229,44 +233,42 @@ var COMPONENTNAME = 'atto_media',
                 '</div>',
             DISPLAY_OPTIONS: '' +
                 '<div class="{{CSS.DISPLAY_OPTIONS}}">' +
-                    '<label>' +
-                        '{{get_string "size" component}}' +
-                        '<div class={{CSS.POSTER_SIZE}}>' +
-                            '<label>' +
-                                '<span class="accesshide">{{get_string "videowidth" component}}</span>' +
-                                '<input type="text" class="{{CSS.WIDTH_INPUT}} input-mini" size="4"/>' +
-                            '</label>' +
+                    '<div class="m-b-1">' +
+                        '<label>{{get_string "size" component}}</label>' +
+                        '<div class="form-inline {{CSS.POSTER_SIZE}}">' +
+                            '<label class="accesshide">{{get_string "videowidth" component}}</label>' +
+                            '<input type="text" class="form-control m-r-1 {{CSS.WIDTH_INPUT}} input-mini" size="4"/>' +
                             ' x ' +
-                            '<label>' +
-                                '<span class="accesshide">{{get_string "videoheight" component}}</span>' +
-                                '<input type="text" class="{{CSS.HEIGHT_INPUT}} input-mini" size="4"/>' +
-                            '</label>' +
+                            '<label class="accesshide">{{get_string "videoheight" component}}</label>' +
+                            '<input type="text" class="form-control m-l-1 {{CSS.HEIGHT_INPUT}} input-mini" size="4"/>' +
                         '</div>' +
-                    '</label>' +
+                    '</div>' +
                     '<div class="clearfix"></div>' +
                     '{{renderPartial "form_components.source" context=this id=CSS.POSTER_SOURCE entersourcelabel="poster"}}' +
                 '<div>',
             ADVANCED_SETTINGS: '' +
                 '<div class="{{CSS.ADVANCED_SETTINGS}}">' +
-                    '<label>' +
-                        '<input type="checkbox" checked="true" class="{{CSS.MEDIA_CONTROLS_TOGGLE}}"/>' +
-                        '{{get_string "controls" component}}' +
-                    '</label>' +
-                    '<label>' +
-                        '<input type="checkbox" class="{{CSS.MEDIA_AUTOPLAY_TOGGLE}}"/>' +
-                        '{{get_string "autoplay" component}}' +
-                    '</label>' +
-                    '<label>' +
-                        '<input type="checkbox" class="{{CSS.MEDIA_MUTE_TOGGLE}}"/>' +
-                        '{{get_string "mute" component}}' +
-                    '</label>' +
-                    '<label>' +
-                        '<input type="checkbox" class="{{CSS.MEDIA_LOOP_TOGGLE}}"/>' +
-                        '{{get_string "loop" component}}' +
-                    '</label>' +
+                    '<div class="form-check">' +
+                        '<input type="checkbox" checked="true" class="form-check-input {{CSS.MEDIA_CONTROLS_TOGGLE}}"' +
+                        'id="media-controls-toggle"/>' +
+                        '<label class="form-check-label" for="media-controls-toggle">{{get_string "controls" component}}</label>' +
+                    '</div>' +
+                    '<div class="form-check">' +
+                        '<input type="checkbox" class="form-check-input {{CSS.MEDIA_AUTOPLAY_TOGGLE}}"' +
+                        'id="media-autoplay-toggle"/>' +
+                        '<label class="form-check-label" for="media-autoplay-toggle">{{get_string "autoplay" component}}</label>' +
+                    '</div>' +
+                    '<div class="form-check">' +
+                        '<input type="checkbox" class="form-check-input {{CSS.MEDIA_MUTE_TOGGLE}}" id="media-mute-toggle"/>' +
+                        '<label class="form-check-label" for="media-mute-toggle">{{get_string "mute" component}}</label>' +
+                    '</div>' +
+                    '<div class="form-check">' +
+                        '<input type="checkbox" class="form-check-input {{CSS.MEDIA_LOOP_TOGGLE}}" id="media-loop-toggle"/>' +
+                        '<label class="form-check-label" for="media-loop-toggle">{{get_string "loop" component}}</label>' +
+                    '</div>' +
                 '</div>',
             TRACK_TABS: '' +
-                '<ul class="nav nav-tabs">' +
+                '<ul class="nav nav-tabs mb-3">' +
                     '<li data-track-kind="{{CSS.TRACK_SUBTITLES}}" class="nav-item">' +
                         '<a class="nav-link active" href="#{{elementid}}_{{id}}_{{CSS.TRACK_SUBTITLES}}"' +
                             ' role="tab" data-toggle="tab">' +
@@ -328,11 +330,11 @@ var COMPONENTNAME = 'atto_media',
                     '</div>' +
                 '</div>',
             TRACK: '' +
-                '<div class="{{CSS.TRACK}}">' +
+                '<div class="m-b-1 {{CSS.TRACK}}">' +
                     '{{renderPartial "form_components.source" context=this id=CSS.TRACK_SOURCE entersourcelabel=sourcelabel}}' +
-                    '<label class="langlabel">' +
-                        '<span>{{get_string "srclang" component}}</span>' +
-                        '<select class="{{CSS.TRACK_LANG_INPUT}}">' +
+                    '<div class="form-group">' +
+                        '<label class="w-100" for="lang-input">{{get_string "srclang" component}}</label>' +
+                        '<select id="lang-input" class="custom-select {{CSS.TRACK_LANG_INPUT}}">' +
                             '<optgroup label="{{get_string "languagesinstalled" component}}">' +
                                 '{{#langsinstalled}}' +
                                     '<option value="{{code}}" {{#default}}selected="selected"{{/default}}>{{lang}}</option>' +
@@ -342,15 +344,15 @@ var COMPONENTNAME = 'atto_media',
                                 '{{#langsavailable}}<option value="{{code}}">{{lang}}</option>{{/langsavailable}}' +
                             '</optgroup>' +
                         '</select>' +
-                    '</label>' +
-                    '<label class="labellabel">' +
-                        '<span>{{get_string "label" component}}</span>' +
-                        '<input class="{{CSS.TRACK_LABEL_INPUT}}" type="text"/>' +
-                    '</label>' +
-                    '<label class="defaultlabel">' +
-                        '<input type="checkbox" class="{{CSS.TRACK_DEFAULT_SELECT}}"/>' +
-                        '{{get_string "default" component}}' +
-                    '</label>' +
+                    '</div>' +
+                    '<div class="form-group">' +
+                        '<label class="w-100" for="track-input">{{get_string "label" component}}</label>' +
+                        '<input id="track-input" class="form-control {{CSS.TRACK_LABEL_INPUT}}" type="text"/>' +
+                    '</div>' +
+                    '<div class="form-check">' +
+                        '<input type="checkbox" class="form-check-input {{CSS.TRACK_DEFAULT_SELECT}}"/>' +
+                        '<label class="form-check-label">{{get_string "default" component}}</label>' +
+                    '</div>' +
                     '{{renderPartial "form_components.add_component" context=this label=addcomponentlabel}}' +
                 '</div>'
         },
index fedd668..3565c9b 100644 (file)
Binary files a/lib/editor/atto/plugins/recordrtc/yui/build/moodle-atto_recordrtc-recording/moodle-atto_recordrtc-recording-debug.js and b/lib/editor/atto/plugins/recordrtc/yui/build/moodle-atto_recordrtc-recording/moodle-atto_recordrtc-recording-debug.js differ
index 4208609..54e9fb4 100644 (file)
Binary files a/lib/editor/atto/plugins/recordrtc/yui/build/moodle-atto_recordrtc-recording/moodle-atto_recordrtc-recording-min.js and b/lib/editor/atto/plugins/recordrtc/yui/build/moodle-atto_recordrtc-recording/moodle-atto_recordrtc-recording-min.js differ
index fedd668..3565c9b 100644 (file)
Binary files a/lib/editor/atto/plugins/recordrtc/yui/build/moodle-atto_recordrtc-recording/moodle-atto_recordrtc-recording.js and b/lib/editor/atto/plugins/recordrtc/yui/build/moodle-atto_recordrtc-recording/moodle-atto_recordrtc-recording.js differ
index 7c2abc4..e61cbec 100644 (file)
@@ -75,6 +75,7 @@ M.atto_recordrtc.audiomodule = {
                 // Empty the array containing the previously recorded chunks.
                 cm.chunks = [];
                 cm.blobSize = 0;
+                cm.uploadBtn.detach('click');
 
                 // Initialize common configurations.
                 var commonConfig = {
index 4069294..3dfb629 100644 (file)
@@ -74,6 +74,7 @@ M.atto_recordrtc.videomodule = {
                 // Empty the array containing the previously recorded chunks.
                 cm.chunks = [];
                 cm.blobSize = 0;
+                cm.uploadBtn.detach('click');
 
                 // Initialize common configurations.
                 var commonConfig = {
index ac4e854..1c68da3 100644 (file)
@@ -3,8 +3,8 @@ div.editor_atto_content th,
 div.editor_atto_content caption {
     border: 1px dashed #bbb;
     position: relative;
-    min-width: 30px;
-    height: 13px;
+    min-width: 2rem;
+    height: 2rem;
 }
 
 div.editor_atto_content caption {
@@ -12,30 +12,18 @@ div.editor_atto_content caption {
 }
 
 div.availablecolors {
-    max-width: 55%;
-    display: inline-block;
-    vertical-align: middle;
+    background-color: #eee;
+    padding: 0.5rem;
 }
-
-div.availablecolors label:not(.hideborder) {
-    border: 1px solid #ddd;
-}
-
-div.availablecolors label {
-    border-radius: 4px;
-    display: inline-block;
-    font-size: 0.1em;
-    padding: 2px;
-    padding-left: 22px;
-}
-
-div.availablecolors label input[type="radio"] {
-    float: none;
-    margin: 0;
-    margin-left: -15px;
-}
-
-input[name="bordersize"],
-input[name="width"] {
-    margin-right: 0.3em;
+div.availablecolors .tablebordercolor,
+div.availablecolors .tablebackgroundcolor {
+    display: inline-flex;
+    justify-content: center;
+    align-items: center;
+    width: 2rem;
+    height: 2rem;
+    text-align: center;
+    vertical-align: sub;
+    border-radius: 25%;
+    margin-right: 0.2rem;
 }
index 1083781..1f3e5d4 100644 (file)
@@ -86,13 +86,13 @@ Feature: Atto tables
     And I click on "Table" "button"
     When I click on "Edit table" "link"
     # Check that the background colour is set correctly.
-    Then the field with xpath "//label/input[@name='backgroundColour' and @value='#FFFFFF']" matches value "1"
+    Then the field with xpath "//div[@class='tablebackgroundcolor']/input[@name='backgroundColour' and @value='#FFFFFF']" matches value "1"
     And the field "Table width (in %)" matches value "100"
     And the field "Borders" matches value "Around table"
     And the field "Style of borders" matches value "dashed"
     And the field "Size of borders" matches value "2"
     # Check that the border colour is set correctly.
-    And the field with xpath "//label/input[@name='borderColour' and @value='#FFFFFF']" matches value "1"
+    And the field with xpath "//div[@class='tablebordercolor']/input[@name='borderColour' and @value='#FFFFFF']" matches value "1"
 
   @javascript
   Scenario: Create a table with background colour and width with border settings off
index c8db3c5..8624a7b 100644 (file)
Binary files a/lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button-debug.js and b/lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button-debug.js differ
index 5b9e915..3039fcd 100644 (file)
Binary files a/lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button-min.js and b/lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button-min.js differ
index c8db3c5..8624a7b 100644 (file)
Binary files a/lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button.js and b/lib/editor/atto/plugins/table/yui/build/moodle-atto_table-button/moodle-atto_table-button.js differ
index f33bc87..5a36fa9 100644 (file)
@@ -41,132 +41,175 @@ var COMPONENT = 'atto_table',
     },
     TEMPLATE = '' +
         '<form class="{{CSS.FORM}}">' +
+            '<div class="m-b-1 form-group row-fluid">' +
+            '<div class="col-sm-4 span4">' +
             '<label for="{{elementid}}_atto_table_caption">{{get_string "caption" component}}</label>' +
-            '<input class="{{CSS.CAPTION}} fullwidth" id="{{elementid}}_atto_table_caption" required />' +
-            '<br/>' +
-            '<br/>' +
-            '<label for="{{elementid}}_atto_table_captionposition" class="sameline">' +
+            '</div><div class="col-sm-8 span8">' +
+            '<input type="text" class="form-control {{CSS.CAPTION}}" id="{{elementid}}_atto_table_caption" required />' +
+            '</div>' +
+            '</div>' +
+            '<div class="m-b-1 form-group row-fluid">' +
+            '<div class="col-sm-4 span4">' +
+            '<label for="{{elementid}}_atto_table_captionposition">' +
             '{{get_string "captionposition" component}}</label>' +
-            '<select class="{{CSS.CAPTIONPOSITION}}" id="{{elementid}}_atto_table_captionposition">' +
+            '</div><div class="col-sm-8 span8">' +
+            '<select class="custom-select {{CSS.CAPTIONPOSITION}}" id="{{elementid}}_atto_table_captionposition">' +
                 '<option value=""></option>' +
                 '<option value="top">{{get_string "top" "editor"}}</option>' +
                 '<option value="bottom">{{get_string "bottom" "editor"}}</option>' +
             '</select>' +
-            '<br/>' +
-            '<label for="{{elementid}}_atto_table_headers" class="sameline">{{get_string "headers" component}}</label>' +
-            '<select class="{{CSS.HEADERS}}" id="{{elementid}}_atto_table_headers">' +
+            '</div>' +
+            '</div>' +
+            '<div class="m-b-1 form-group row-fluid">' +
+            '<div class="col-sm-4 span4">' +
+            '<label for="{{elementid}}_atto_table_headers">{{get_string "headers" component}}</label>' +
+            '</div><div class="col-sm-8 span8">' +
+            '<select class="custom-select {{CSS.HEADERS}}" id="{{elementid}}_atto_table_headers">' +
                 '<option value="columns">{{get_string "columns" component}}' + '</option>' +
                 '<option value="rows">{{get_string "rows" component}}' + '</option>' +
                 '<option value="both">{{get_string "both" component}}' + '</option>' +
             '</select>' +
-            '<br/>' +
+            '</div>' +
+            '</div>' +
             '{{#if nonedit}}' +
-                '<label for="{{elementid}}_atto_table_rows" class="sameline">{{get_string "numberofrows" component}}</label>' +
-                '<input class="{{CSS.ROWS}}" type="number" value="3" ' +
+                '<div class="m-b-1 form-group row-fluid">' +
+                '<div class="col-sm-4 span4">' +
+                '<label for="{{elementid}}_atto_table_rows">{{get_string "numberofrows" component}}</label>' +
+                '</div><div class="col-sm-8 span8">' +
+                '<input class="form-control w-auto {{CSS.ROWS}}" type="number" value="3" ' +
                 'id="{{elementid}}_atto_table_rows" size="8" min="1" max="50"/>' +
-                '<br/>' +
+                '</div>' +
+                '</div>' +
+                '<div class="m-b-1 form-group row-fluid">' +
+                '<div class="col-sm-4 span4">' +
                 '<label for="{{elementid}}_atto_table_columns" ' +
-                'class="sameline">{{get_string "numberofcolumns" component}}</label>' +
-                '<input class="{{CSS.COLUMNS}}" type="number" value="3" id="{{elementid}}_atto_table_columns"' +
+                '>{{get_string "numberofcolumns" component}}</label>' +
+                '</div><div class="col-sm-8 span8">' +
+                '<input class="form-control w-auto {{CSS.COLUMNS}}" type="number" value="3" ' +
+                    'id="{{elementid}}_atto_table_columns"' +
                 'size="8" min="1" max="20"/>' +
-                '<br/>' +
+                '</div>' +
+                '</div>' +
             '{{/if}}' +
             '{{#if allowStyling}}' +
                 '<fieldset>' +
                 '<legend class="mdl-align">{{get_string "appearance" component}}</legend>' +
                 '{{#if allowBorders}}' +
-                    '<label for="{{elementid}}_atto_table_borders" class="sameline">{{get_string "borders" component}}</label>' +
-                    '<select name="borders" class="{{CSS.BORDERS}}" id="{{elementid}}_atto_table_borders">' +
+                    '<div class="m-b-1 form-group row-fluid">' +
+                    '<div class="col-sm-4 span4">' +
+                    '<label for="{{elementid}}_atto_table_borders">{{get_string "borders" component}}</label>' +
+                    '</div><div class="col-sm-8 span8">' +
+                    '<select name="borders" class="custom-select {{CSS.BORDERS}}" id="{{elementid}}_atto_table_borders">' +
                         '<option value="default">{{get_string "themedefault" component}}' + '</option>' +
                         '<option value="outer">{{get_string "outer" component}}' + '</option>' +
                         '<option value="all">{{get_string "all" component}}' + '</option>' +
                     '</select>' +
-                    '<br>' +
-                    '<label for="{{elementid}}_atto_table_borderstyle" class="sameline">' +
+                    '</div>' +
+                    '</div>' +
+                    '<div class="m-b-1 form-group row-fluid">' +
+                    '<div class="col-sm-4 span4">' +
+                    '<label for="{{elementid}}_atto_table_borderstyle">' +
                     '{{get_string "borderstyles" component}}</label>' +
-                    '<select name="borderstyles" class="{{CSS.BORDERSTYLE}}" id="{{elementid}}_atto_table_borderstyle">' +
+                    '</div><div class="col-sm-8 span8">' +
+                    '<select name="borderstyles" class="custom-select {{CSS.BORDERSTYLE}}" ' +
+                        'id="{{elementid}}_atto_table_borderstyle">' +
                         '{{#each borderStyles}}' +
                             '<option value="' + '{{this}}' + '">' + '{{get_string this ../component}}' + '</option>' +
                         '{{/each}}' +
                     '</select>' +
-                    '<br>' +
-                    '<label for="{{elementid}}_atto_table_bordersize" class="sameline">' +
+                    '</div>' +
+                    '</div>' +
+                    '<div class="m-b-1 form-group row-fluid">' +
+                    '<div class="col-sm-4 span4">' +
+                    '<label for="{{elementid}}_atto_table_bordersize">' +
                     '{{get_string "bordersize" component}}</label>' +
-                    '<input name="bordersize" id="{{elementid}}_atto_table_bordersize" class="{{CSS.BORDERSIZE}}"' +
+                    '</div><div class="col-sm-8 span8">' +
+                    '<div class="form-inline">' +
+                    '<input name="bordersize" id="{{elementid}}_atto_table_bordersize" ' +
+                    'class="form-control w-auto m-r-1 {{CSS.BORDERSIZE}}"' +
                     'type="number" value="1" size="8" min="1" max="50"/>' +
-                    '<label style="display: inline-block;">{{CSS.BORDERSIZEUNIT}}</label>' +
-                    '<br>' +
-                    '<label for="{{elementid}}_atto_table_bordercolour" class="sameline">' +
+                    '<label>{{CSS.BORDERSIZEUNIT}}</label>' +
+                    '</div>' +
+                    '</div>' +
+                    '</div>' +
+                    '<div class="m-b-1 form-group row-fluid">' +
+                    '<div class="col-sm-4 span4">' +
+                    '<label for="{{elementid}}_atto_table_bordercolour">' +
                     '{{get_string "bordercolour" component}}</label>' +
+                    '</div><div class="col-sm-8 span8">' +
                     '<div id="{{elementid}}_atto_table_bordercolour"' +
-                    'class="{{CSS.BORDERCOLOUR}} {{CSS.AVAILABLECOLORS}}" size="1">' +
-                        '<label class="hideborder" for="{{../elementid}}_atto_table_bordercolour_-1"' +
-                        'style="background-color:transparent;color:transparent">' +
-
+                    'class="form-inline {{CSS.BORDERCOLOUR}} {{CSS.AVAILABLECOLORS}}" size="1">' +
+                        '<div class="tablebordercolor" style="background-color:transparent;color:transparent">' +
                             '<input id="{{../elementid}}_atto_table_bordercolour_-1"' +
-                            'type="radio" name="borderColour" value="none" checked="checked"' +
+                            'type="radio" class="m-0" name="borderColour" value="none" checked="checked"' +
                             'title="{{get_string "themedefault" component}}"></input>' +
-
-                            '{{get_string "themedefault" component}}' +
-                        '</label>' +
+                            '<label for="{{../elementid}}_atto_table_bordercolour_-1" class="accesshide">' +
+                            '{{get_string "themedefault" component}}</label>' +
+                        '</div>' +
                         '{{#each availableColours}}' +
-                            '<label for="{{../elementid}}_atto_table_bordercolour_{{@index}}"' +
-                            'style="background-color:{{this}};color:{{this}}">' +
-
+                            '<div class="tablebordercolor" style="background-color:{{this}};color:{{this}}">' +
                                 '<input id="{{../elementid}}_atto_table_bordercolour_{{@index}}"' +
-                                'type="radio" name="borderColour" value="' + '{{this}}' + '" title="{{this}}">' +
-
-                                '{{this}}' +
-                            '</label>' +
+                                'type="radio" class="m-0" name="borderColour" value="' + '{{this}}' + '" title="{{this}}">' +
+                                '<label for="{{../elementid}}_atto_table_bordercolour_{{@index}}" class="accesshide">' +
+                                '{{this}}</label>' +
+                            '</div>' +
                         '{{/each}}' +
                     '</div>' +
-                    '<br>' +
+                    '</div>' +
+                    '</div>' +
                 '{{/if}}' +
                 '{{#if allowBackgroundColour}}' +
-                    '<label for="{{elementid}}_atto_table_backgroundcolour" class="sameline">' +
+                    '<div class="m-b-1 form-group row-fluid">' +
+                    '<div class="col-sm-4 span4">' +
+                    '<label for="{{elementid}}_atto_table_backgroundcolour">' +
                     '{{get_string "backgroundcolour" component}}</label>' +
+                    '</div><div class="col-sm-8 span8">' +
                     '<div id="{{elementid}}_atto_table_backgroundcolour"' +
-                    'class="{{CSS.BACKGROUNDCOLOUR}} {{CSS.AVAILABLECOLORS}}" size="1">' +
-                        '<label class="hideborder" for="{{../elementid}}_atto_table_backgroundcolour_-1"' +
-                        'style="background-color:transparent;color:transparent">' +
-
+                    'class="form-inline {{CSS.BACKGROUNDCOLOUR}} {{CSS.AVAILABLECOLORS}}" size="1">' +
+                        '<div class="tablebackgroundcolor" style="background-color:transparent;color:transparent">' +
                             '<input id="{{../elementid}}_atto_table_backgroundcolour_-1"' +
-                            'type="radio" name="backgroundColour" value="none" checked="checked"' +
+                            'type="radio" class="m-0" name="backgroundColour" value="none" checked="checked"' +
                             'title="{{get_string "themedefault" component}}"></input>' +
-
-                            '{{get_string "themedefault" component}}' +
-                        '</label>' +
+                            '<label for="{{../elementid}}_atto_table_backgroundcolour_-1" class="accesshide">' +
+                            '{{get_string "themedefault" component}}</label>' +
+                        '</div>' +
 
                         '{{#each availableColours}}' +
-                            '<label for="{{../elementid}}_atto_table_backgroundcolour_{{@index}}"' +
-                            'style="background-color:{{this}};color:{{this}}">' +
-
+                            '<div class="tablebackgroundcolor" style="background-color:{{this}};color:{{this}}">' +
                                 '<input id="{{../elementid}}_atto_table_backgroundcolour_{{@index}}"' +
-                                'type="radio" name="backgroundColour" value="' + '{{this}}' + '" title="{{this}}">' +
-
-                                '{{this}}' +
-                            '</label>' +
+                                'type="radio" class="m-0" name="backgroundColour" value="' + '{{this}}' + '" title="{{this}}">' +
+                                '<label for="{{../elementid}}_atto_table_backgroundcolour_{{@index}}" class="accesshide">' +
+                                '{{this}}</label>' +
+                            '</div>' +
                         '{{/each}}' +
                     '</div>' +
-                    '<br>' +
+                    '</div>' +
+                    '</div>' +
                 '{{/if}}' +
                 '{{#if allowWidth}}' +
-                    '<label for="{{elementid}}_atto_table_width" class="sameline">' +
+                    '<div class="m-b-1 form-group row-fluid">' +
+                    '<div class="col-sm-4 span4">' +
+                    '<label for="{{elementid}}_atto_table_width">' +
                     '{{get_string "width" component}}</label>' +
-                    '<input name="width" id="{{elementid}}_atto_table_width" class="{{CSS.WIDTH}}" size="8" ' +
+                    '</div><div class="col-sm-8 span8">' +
+                    '<div class="form-inline">' +
+                    '<input name="width" id="{{elementid}}_atto_table_width" ' +
+                        'class="form-control w-auto m-r-1 {{CSS.WIDTH}}" size="8" ' +
                         'type="number" min="0" max="100"/>' +
-                    '<label style="display: inline-block;">{{CSS.WIDTHUNIT}}</label>' +
-                    '<br>' +
+                    '<label>{{CSS.WIDTHUNIT}}</label>' +
+                    '</div>' +
+                    '</div>' +
+                    '</div>' +
                 '{{/if}}' +
                 '</fieldset>' +
             '{{/if}}' +
             '<div class="mdl-align">' +
             '<br/>' +
             '{{#if edit}}' +
-                '<button class="submit" type="submit">{{get_string "updatetable" component}}</button>' +
+                '<button class="btn btn-default submit" type="submit">{{get_string "updatetable" component}}</button>' +
             '{{/if}}' +
             '{{#if nonedit}}' +
-                '<button class="submit" type="submit">{{get_string "createtable" component}}</button>' +
+                '<button class="btn btn-default submit" type="submit">{{get_string "createtable" component}}</button>' +
             '{{/if}}' +
             '</div>' +
         '</form>',
index 84c777e..f2b74e1 100644 (file)
@@ -107,10 +107,10 @@ div.editor_atto_toolbar div.atto_group {
     margin: 4px;
 }
 
-.atto_form label.sameline {
+/*.atto_form label.sameline {
     display: inline-block;
     min-width: 10em;
-}
+}*/
 
 .atto_form textarea.fullwidth,
 .atto_form input.fullwidth {
@@ -118,14 +118,13 @@ div.editor_atto_toolbar div.atto_group {
 }
 
 .atto_form {
-    padding-left: 30px;
-    padding-right: 30px;
+    padding: 0.5rem;
 }
 
-.atto_form label {
+/*.atto_form label {
     display: block;
     margin: 0 0 5px 0;
-}
+}*/
 
 .atto_control {
     position: absolute;
index e81dee0..34d481f 100644 (file)
@@ -90,10 +90,10 @@ class migrate_message_data extends \core\task\adhoc_task {
                             $this->migrate_data($userid, $otheruserid);
                             $transaction->allow_commit();
                         } catch (\Throwable $e) {
-                            $updatepreference = false;
+                            throw $e;
+                        } finally {
+                            $lock->release();
                         }
-
-                        $lock->release();
                     } else {
                         // Couldn't get a lock, move on to next user but make sure we don't update user preference so
                         // we still try again.
@@ -172,7 +172,7 @@ class migrate_message_data extends \core\task\adhoc_task {
         $tabledata->useridto = $notification->useridto;
         $tabledata->subject = $notification->subject;
         $tabledata->fullmessage = $notification->fullmessage;
-        $tabledata->fullmessageformat = $notification->fullmessageformat;
+        $tabledata->fullmessageformat = $notification->fullmessageformat ?? FORMAT_MOODLE;
         $tabledata->fullmessagehtml = $notification->fullmessagehtml;
         $tabledata->smallmessage = $notification->smallmessage;
         $tabledata->component = $notification->component;
@@ -210,7 +210,7 @@ class migrate_message_data extends \core\task\adhoc_task {
         $tabledata->conversationid = $conversationid;
         $tabledata->subject = $message->subject;
         $tabledata->fullmessage = $message->fullmessage;
-        $tabledata->fullmessageformat = $message->fullmessageformat;
+        $tabledata->fullmessageformat = $message->fullmessageformat ?? FORMAT_MOODLE;
         $tabledata->fullmessagehtml = $message->fullmessagehtml;
         $tabledata->smallmessage = $message->smallmessage;
         $tabledata->timecreated = $message->timecreated;
index b67fdc8..37fea75 100644 (file)
Binary files a/message/output/popup/amd/build/message_popover_controller.min.js and b/message/output/popup/amd/build/message_popover_controller.min.js differ
index 4d099a4..b241a56 100644 (file)
Binary files a/message/output/popup/amd/build/notification_popover_controller.min.js and b/message/output/popup/amd/build/notification_popover_controller.min.js differ
index 499980b..6ea5608 100644 (file)
@@ -57,7 +57,7 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/str',
         this.initialLoad = false;
 
         // Let's find out how many unread messages there are.
-        this.loadUnreadMessageCount();
+        this.unreadCount = this.root.find(SELECTORS.COUNT_CONTAINER).html();
     };
 
     /**
@@ -139,21 +139,6 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/str',
         this.root.find(SELECTORS.COUNT_CONTAINER).addClass('hidden');
     };
 
-    /**
-     * Ask the server how many unread messages are left, render the value
-     * as a badge on the menu toggle and update the aria labels on the menu
-     * toggle.
-     *
-     * @method loadUnreadMessageCount
-     */
-    MessagePopoverController.prototype.loadUnreadMessageCount = function() {
-        MessageRepo.countUnreadConversations({useridto: this.userId}).then(function(count) {
-            this.unreadCount = count;
-            this.renderUnreadCount();
-            this.updateButtonAriaLabel();
-        }.bind(this)).catch(Notification.exception);
-    };
-
     /**
      * Render the message data with the appropriate template and add it to the DOM.
      *
index de45501..9aa7630 100644 (file)
@@ -60,7 +60,7 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/str', 'core/url',
         this.initialLoad = false;
 
         // Let's find out how many unread notifications there are.
-        this.loadUnreadNotificationCount();
+        this.unreadCount = this.root.find(SELECTORS.COUNT_CONTAINER).html();
     };
 
     /**
@@ -188,21 +188,6 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/str', 'core/url',
         this.root.find(SELECTORS.COUNT_CONTAINER).addClass('hidden');
     };
 
-    /**
-     * Ask the server how many unread notifications are left, render the value
-     * as a badge on the menu toggle and update the aria labels on the menu
-     * toggle.
-     *
-     * @method loadUnreadNotificationCount
-     */
-    NotificationPopoverController.prototype.loadUnreadNotificationCount = function() {
-        NotificationRepo.countUnread({useridto: this.userId}).then(function(count) {
-            this.unreadCount = count;
-            this.renderUnreadCount();
-            this.updateButtonAriaLabel();
-        }.bind(this)).catch(DebugNotification.exception);
-    };
-
     /**
      * Find the notification element for the given id.
      *
@@ -239,8 +224,8 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/str', 'core/url',
 
             // Link to mark read page before loading the actual link.
             notification.contexturl = URL.relativeUrl('message/output/popup/mark_notification_read.php', {
-                redirecturl: notification.contexturl,
                 notificationid: notification.id,
+                redirecturl: notification.contexturl
             });
 
             var promise = Templates.render('message_popup/notification_content_item', notification)
index 4c4f910..3253109 100644 (file)
@@ -14,8 +14,6 @@
 // You should have received a copy of the GNU General Public License
 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 
-defined('MOODLE_INTERNAL') || die();
-
 /**
  * Contains standard functions for message_popup.
  *
@@ -24,6 +22,8 @@ defined('MOODLE_INTERNAL') || die();
  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
 
+defined('MOODLE_INTERNAL') || die();
+
 /**
  * Renders the popup.
  *
@@ -45,8 +45,10 @@ function message_popup_render_navbar_output(\renderer_base $renderer) {
 
     // Add the messages popover.
     if (!empty($CFG->messaging)) {
+        $unreadcount = \core_message\api::count_unread_conversations($USER);
         $context = [
             'userid' => $USER->id,
+            'unreadcount' => $unreadcount,
             'urls' => [
                 'seeall' => (new moodle_url('/message/index.php'))->out(),
                 'writeamessage' => (new moodle_url('/message/index.php', ['contactsfirst' => 1]))->out(),
@@ -59,8 +61,10 @@ function message_popup_render_navbar_output(\renderer_base $renderer) {
     // Add the notifications popover.
     $enabled = \core_message\api::is_processor_enabled("popup");
     if ($enabled) {
+        $unreadcount = \message_popup\api::count_unread_popup_notifications($USER->id);
         $context = [
             'userid' => $USER->id,
+            'unreadcount' => $unreadcount,
             'urls' => [
                 'seeall' => (new moodle_url('/message/output/popup/notifications.php'))->out(),
                 'preferences' => (new moodle_url('/message/notificationpreferences.php', ['userid' => $USER->id]))->out(),
index 0355993..75b363d 100644 (file)
@@ -45,7 +45,7 @@
     {{$togglelabel}}{{#str}} showmessagewindownonew, message {{/str}}{{/togglelabel}}
     {{$togglecontent}}
         {{#pix}} t/message, core, {{#str}} togglemessagemenu, message {{/str}} {{/pix}}
-        <div class="count-container hidden" data-region="count-container"></div>
+        <div class="count-container {{^unreadcount}}hidden{{/unreadcount}}" data-region="count-container">{{unreadcount}}</div>
     {{/togglecontent}}
 
     {{$containerlabel}}{{#str}} notificationwindow, message {{/str}}{{/containerlabel}}
index 97efbff..602d106 100644 (file)
@@ -45,7 +45,7 @@
     {{$togglelabel}}{{#str}} shownotificationwindownonew, message {{/str}}{{/togglelabel}}
     {{$togglecontent}}
         {{#pix}} i/notifications, core, {{#str}} togglenotificationmenu, message {{/str}} {{/pix}}
-        <div class="count-container hidden" data-region="count-container"></div>
+        <div class="count-container {{^unreadcount}}hidden{{/unreadcount}}" data-region="count-container">{{unreadcount}}</div>
     {{/togglecontent}}
 
     {{$containerlabel}}{{#str}} notificationwindow, message {{/str}}{{/containerlabel}}
index 72c1d0a..3ec3009 100644 (file)
@@ -268,6 +268,62 @@ class core_message_migrate_message_data_task_testcase extends advanced_testcase
         }
     }
 
+    /**
+     * Test migrating a legacy message that contains null as the format.
+     */
+    public function test_migrating_message_null_format() {
+        global $DB;
+
+        // Create users to test with.
+        $user1 = $this->getDataGenerator()->create_user();
+        $user2 = $this->getDataGenerator()->create_user();
+
+        $this->create_legacy_message_or_notification($user1->id, $user2->id, null, false, null, null);
+
+        // Now, let's execute the task for user 1.
+        $task = new \core_message\task\migrate_message_data();
+        $task->set_custom_data(
+            [
+                'userid' => $user1->id
+            ]
+        );
+        $task->execute();
+
+        $messages = $DB->get_records('messages');
+        $this->assertCount(1, $messages);
+
+        $message = reset($messages);
+        $this->assertEquals(FORMAT_MOODLE, $message->fullmessageformat);
+    }
+
+    /**
+     * Test migrating a legacy notification that contains null as the format.
+     */
+    public function test_migrating_notification_null_format() {
+        global $DB;
+
+        // Create users to test with.
+        $user1 = $this->getDataGenerator()->create_user();
+        $user2 = $this->getDataGenerator()->create_user();
+
+        $this->create_legacy_message_or_notification($user1->id, $user2->id, null, true, null, null);
+
+        // Now, let's execute the task for user 1.
+        $task = new \core_message\task\migrate_message_data();
+        $task->set_custom_data(
+            [
+                'userid' => $user1->id
+            ]
+        );
+        $task->execute();
+
+        $notifications = $DB->get_records('notifications');
+        $this->assertCount(1, $notifications);
+
+        $notification = reset($notifications);
+        $this->assertEquals(FORMAT_MOODLE, $notification->fullmessageformat);
+    }
+
     /**
      * Creates a legacy message or notification to be used for testing.
      *
@@ -276,11 +332,12 @@ class core_message_migrate_message_data_task_testcase extends advanced_testcase
      * @param int $timecreated
      * @param bool $notification
      * @param int|null $timeread The time the message/notification was read, null if it hasn't been.
+     * @param string|int|null $format The format of the message.
      * @return int The id of the message (in either the message or message_read table)
      * @throws dml_exception
      */
     private function create_legacy_message_or_notification($useridfrom, $useridto, $timecreated = null,
-            $notification = false, $timeread = null) {
+            $notification = false, $timeread = null, $format = FORMAT_PLAIN) {
         global $DB;
 
         $tabledata = new \stdClass();
@@ -312,7 +369,7 @@ class core_message_migrate_message_data_task_testcase extends advanced_testcase
         $tabledata->useridto = $useridto;
         $tabledata->subject = 'Subject ' . $timecreated;
         $tabledata->fullmessage = 'Full message ' . $timecreated;
-        $tabledata->fullmessageformat = FORMAT_PLAIN;
+        $tabledata->fullmessageformat = $format;
         $tabledata->fullmessagehtml = 'Full message HTML ' . $timecreated;
         $tabledata->smallmessage = 'Small message ' . $timecreated;
         $tabledata->timecreated = $timecreated;
index ad5ba63..071f6e9 100644 (file)
@@ -277,7 +277,8 @@ class assign_grading_table extends table_sql implements renderable {
                                  s.status = :submitted AND
                                  (s.timemodified >= g.timemodified OR g.timemodified IS NULL OR g.grade IS NULL';
 
-                if ($this->assignment->get_grade_item()->gradetype == GRADE_TYPE_SCALE) {
+                // Assignment grade is set to the negative grade scale id when scales are used.
+                if ($this->assignment->get_instance()->grade < 0) {
                     // Scale grades are set to -1 when not graded.
                     $where .= ' OR g.grade = -1';
                 }
index db8958a..c454974 100644 (file)
@@ -189,6 +189,40 @@ class mod_assign_locallib_testcase extends advanced_testcase {
         }
     }
 
+    /**
+     * Test filter by requires grading.
+     *
+     * This is specifically checking an assignment with no grade to make sure we do not
+     * get an exception thrown when rendering the grading table for this type of assignment.
+     */
+    public function test_gradingtable_filter_by_requiresgrading_no_grade() {
+        global $PAGE;
+
+        $this->resetAfterTest();
+
+        $course = $this->getDataGenerator()->create_course();
+        $teacher = $this->getDataGenerator()->create_and_enrol($course, 'teacher');
+        $this->setUser($teacher);
+        $assign = $this->create_instance($course, [
+                'assignsubmission_onlinetext_enabled' => 1,
+                'assignfeedback_comments_enabled' => 0,
+                'grade' => GRADE_TYPE_NONE
+            ]);
+
+        $PAGE->set_url(new moodle_url('/mod/assign/view.php', array(
+            'id' => $assign->get_course_module()->id,
+            'action' => 'grading',
+        )));
+
+        // Render the table with the requires grading filter.
+        $gradingtable = new assign_grading_table($assign, 1, ASSIGN_FILTER_REQUIRE_GRADING, 0, true);
+        $output = $assign->get_renderer()->render($gradingtable);
+
+        // Test that the filter function does not throw errors for assignments with no grade.
+        $this->assertContains(get_string('nothingtodisplay'), $output);
+    }
+
+
     /**
      * Test submissions with extension date.
      */
@@ -2748,7 +2782,7 @@ class mod_assign_locallib_testcase extends advanced_testcase {
 
         $cm = get_coursemodule_from_instance('assign', $assign->get_instance()->id);
         $context = context_module::instance($cm->id);
-        $assign = new testable_assign($context, $cm, $course);
+        $assign = new mod_assign_testable_assign($context, $cm, $course);
 
         // Check that other teachers can't view this submission.
         $this->setUser($otherteacher);
index df0a726..84652e4 100644 (file)
@@ -350,7 +350,7 @@ if (!empty($forum)) {      // User is starting a new discussion in a forum
                 $event->add_record_snapshot('forum_discussions', $discussion);
                 $event->trigger();
 
-                redirect("view.php?f=$discussion->forum");
+                redirect(new moodle_url('/mod/forum/view.php', ['f' => $discussion->forum]));
 
             } else if (forum_delete_post($post, has_capability('mod/forum:deleteanypost', $modcontext),
                 $course, $cm, $forum)) {
@@ -845,7 +845,7 @@ if ($mform_post->is_cancelled()) {
 
     } else { // Adding a new discussion.
         // The location to redirect to after successfully posting.
-        $redirectto = new moodle_url('view.php', array('f' => $fromform->forum));
+        $redirectto = new moodle_url('/mod/forum/view.php', array('f' => $fromform->forum));
 
         $fromform->mailnow = empty($fromform->mailnow) ? 0 : 1;
 
index 744dae9..25379ce 100644 (file)
@@ -166,7 +166,7 @@ class provider implements
             $params['itemid'] = $itemid;
         }
         if ($userid) {
-            $params['userid'] = $userid;
+            $params['tiuserid'] = $userid;
         }
         $DB->delete_records('tag_instance', $params);
     }
index ccbda47..56c8ae9 100644 (file)
@@ -121,6 +121,35 @@ class core_tag_privacy_testcase extends provider_testcase {
         $this->assertEquals($expectedtagcount, $DB->count_records('tag_instance'));
     }
 
+    /**
+     * Test method delete_item_tags() with userid.
+     */
+    public function test_delete_item_tags_with_userid() {
+        global $DB;
+
+        $this->resetAfterTest(true);
+        // Create a course to tag.
+        $course = $this->getDataGenerator()->create_course();
+        $context = context_course::instance($course->id);
+
+        // Create a user to perform tagging.
+        $user = $this->getDataGenerator()->create_user();
+        $this->setUser($user);
+
+        // Tag courses.
+        core_tag_tag::set_item_tags('core_course', 'course', $course->id, $context, ['Tag 1', 'Tag 2'], $user->id);
+        $expectedtagcount = $DB->count_records('tag_instance');
+
+        // Delete tags for course. Use wrong userid.
+        core_tag\privacy\provider::delete_item_tags($context, 'core_course', 'course', null, 1);
+        $this->assertEquals($expectedtagcount, $DB->count_records('tag_instance'));
+
+        $expectedtagcount -= 2;
+        // Delete tags for course. Use correct userid.
+        core_tag\privacy\provider::delete_item_tags($context, 'core_course', 'course', null, $user->id);
+        $this->assertEquals($expectedtagcount, $DB->count_records('tag_instance'));
+    }
+
     /**
      * Test method delete_item_tags_select().
      */
index fc90019..fe36c9b 100644 (file)
Binary files a/theme/boost/amd/build/drawer.min.js and b/theme/boost/amd/build/drawer.min.js differ
index 6b48b55..cc9042b 100644 (file)
@@ -32,6 +32,8 @@ define(['jquery', 'core/custom_interaction_events', 'core/log'],
         SECTION: '.list-group-item[href*="#section-"]'
     };
 
+    var small = $(document).width() < 768;
+
     /**
      * Constructor for the Drawer.
      *
@@ -52,6 +54,10 @@ define(['jquery', 'core/custom_interaction_events', 'core/log'],
             var hidden = trigger.attr('aria-expanded') == 'false';
             var side = trigger.attr('data-side');
             var body = $(SELECTORS.BODY);
+            var preference = trigger.attr('data-preference');
+            if (small) {
+                M.util.set_user_preference(preference, 'false');
+            }
 
             drawer.on('mousewheel DOMMouseScroll', this.preventPageScroll);
 
@@ -64,7 +70,6 @@ define(['jquery', 'core/custom_interaction_events', 'core/log'],
         }.bind(this));
 
         this.registerEventListeners();
-        var small = $(document).width() < 768;
         if (small) {
             this.closeAll();
         }
@@ -83,7 +88,9 @@ define(['jquery', 'core/custom_interaction_events', 'core/log'],
             body.removeClass('drawer-open-' + side);
             drawer.attr('aria-hidden', 'true');
             drawer.addClass('closed');
-            M.util.set_user_preference(preference, 'false');
+            if (!small) {
+                M.util.set_user_preference(preference, 'false');
+            }
         });
     };
 
@@ -100,6 +107,9 @@ define(['jquery', 'core/custom_interaction_events', 'core/log'],
         var body = $(SELECTORS.BODY);
         var side = trigger.attr('data-side');
         var preference = trigger.attr('data-preference');
+        if (small) {
+            M.util.set_user_preference(preference, 'false');
+        }
 
         body.addClass('drawer-ease');
         var open = trigger.attr('aria-expanded') == 'true';
@@ -110,14 +120,18 @@ define(['jquery', 'core/custom_interaction_events', 'core/log'],
             drawer.focus();
             body.addClass('drawer-open-' + side);
             drawer.removeClass('closed');
-            M.util.set_user_preference(preference, 'true');
+            if (!small) {
+                M.util.set_user_preference(preference, 'true');
+            }
         } else {
             // Close.
             body.removeClass('drawer-open-' + side);
             trigger.attr('aria-expanded', 'false');
             drawer.attr('aria-hidden', 'true');
             drawer.addClass('closed');
-            M.util.set_user_preference(preference, 'false');
+            if (!small) {
+                M.util.set_user_preference(preference, 'false');
+            }
         }
     };
 
@@ -153,7 +167,6 @@ define(['jquery', 'core/custom_interaction_events', 'core/log'],
         }.bind(this));
 
         $(SELECTORS.SECTION).click(function() {
-            var small = $(document).width() < 768;
             if (small) {
                 this.closeAll();
             }
index bf755b7..379e50b 100644 (file)
 
 namespace theme_boost\privacy;
 
+use \core_privacy\local\metadata\collection;
+
 defined('MOODLE_INTERNAL') || die();
 
 /**
- * The boost theme does not store any data.
+ * The boost theme stores a user preference data.
  *
  * @copyright  2018 Andrew Nicols <andrew@nicols.co.uk>
  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  */
-class provider implements \core_privacy\local\metadata\null_provider {
+class provider implements
+    // This plugin has data.
+    \core_privacy\local\metadata\provider,
+    // This plugin has some sitewide user preferences to export.
+    \core_privacy\local\request\user_preference_provider {
+
+    /** The user preference for the navigation drawer. */
+    const DRAWER_OPEN_NAV = 'drawer-open-nav';
+
+    /**
+     * Returns meta data about this system.
+     *
+     * @param  collection $items The initialised item collection to add items to.
+     * @return collection A listing of user data stored through this system.
+     */
+    public static function get_metadata(collection $items) : collection {
+        $items->add_user_preference(self::DRAWER_OPEN_NAV, 'privacy:metadata:preference:draweropennav');
+        return $items;
+    }
 
     /**
-     * Get the language string identifier with the component's language
-     * file to explain why this plugin stores no data.
+     * Store all user preferences for the plugin.
      *
-     * @return  string
+     * @param int $userid The userid of the user whose data is to be exported.
      */
-    public static function get_reason() : string {
-        return 'privacy:metadata';
+    public static function export_user_preferences(int $userid) {
+        $draweropennavpref = get_user_preferences(self::DRAWER_OPEN_NAV, null, $userid);
+
+        if (isset($draweropennavpref)) {
+            $preferencestring = get_string('privacy:drawernavclosed', 'theme_boost');
+            if ($draweropennavpref == 'true') {
+                $preferencestring = get_string('privacy:drawernavopen', 'theme_boost');
+            }
+            \core_privacy\local\request\writer::export_user_preference(
+                'theme_boost',
+                self::DRAWER_OPEN_NAV,
+                $draweropennavpref,
+                $preferencestring
+            );
+        }
     }
 }
index 2f3b990..627ccf7 100644 (file)
@@ -49,3 +49,6 @@ $string['rawscss_desc'] = 'Use this field to provide SCSS or CSS code which will
 $string['rawscsspre'] = 'Raw initial SCSS';
 $string['rawscsspre_desc'] = 'In this field you can provide initialising SCSS code, it will be injected before everything else. Most of the time you will use this setting to define variables.';
 $string['region-side-pre'] = 'Right';
+$string['privacy:metadata:preference:draweropennav'] = 'The user\'s preference for hiding or showing the drawer menu navigation.';
+$string['privacy:drawernavclosed'] = 'The current preference for the navigation drawer is closed.';
+$string['privacy:drawernavopen'] = 'The current preference for the navigation drawer is open.';
index 3442487..4d01c21 100644 (file)
@@ -127,9 +127,9 @@ $tag-font-weight: bold !default;
     background-size: ($input-height / 2) ($input-height / 2);
 }
 
-.form-check-input {
-    position: static;
-}
+// .form-check-input {
+//     position: static;
+// }
 
 @mixin tag-variant($color) {
     background-color: $color;
index af0e685..53e5411 100644 (file)
@@ -2108,3 +2108,10 @@ $footer-link-color: $bg-inverse-link-color !default;
 .open.atto_menu > .dropdown-menu {
     display: block;
 }
+div.editor_atto_toolbar button .icon {
+    color: $gray-700;
+}
+.w-auto {
+    width: auto;
+}
+
index 1f2467a..26557f8 100644 (file)
@@ -126,13 +126,6 @@ body:not(.jsenabled) .langmenu:hover > .dropdown-menu,
     overflow-y: auto;
 }
 
-// Extends bootstrapbase/less/bootstrap/type.less
-// to enable ol lists to use a larger number set.
-
-ol {
-    margin: 0 0 $line-height-base / 2 2.5em;
-}
-
 // Set menus in the fixed header to scroll vertically when they are longer than the page.
 .navbar.fixed-top .dropdown .dropdown-menu {
     max-height: calc(100vh - #{$navbar-height});
index 48d72ed..ca9d291 100644 (file)
                 <div class="fp-license form-group row">
                     <label class="form-control-label col-4">{{#str}}chooselicense, repository{{/str}}</label>
                     <div class="col-8">
-                        <select class="form-control"></select>
+                        <select class="custom-select"></select>
                     </div>
                 </div>
                 <div class="fp-path form-group row">
                     <label class="form-control-label col-4">{{#str}}path, repository{{/str}}</label>
                     <div class="col-8">
-                        <select class="form-control"></select>
+                        <select class="custom-select"></select>
                     </div>
                 </div>
                 <div class="fp-original form-group row">
index 7002e76..c9d6cae 100644 (file)
@@ -22,7 +22,7 @@
                 </div>
                 <div class="fp-login-select form-group">
                     <label class="form-control-label"></label>
-                    <select class="form-control"></select>
+                    <select class="custom-select"></select>
                 </div>
                 <div class="fp-login-input form-group">
                     <label class="form-control-label"></label>
index 110a5e8..d27da6e 100644 (file)
@@ -41,7 +41,7 @@
             </div>
             <div class="fp-setlicense form-group row">
                 <label class="col-form-label">{{#str}}chooselicense, repository{{/str}}</label>
-                <select class="form-control"></select>
+                <select class="custom-select"></select>
             </div>
             <div class="form-group row">
                 <div class="fp-select-buttons">
index 4caf07b..b3aec8e 100644 (file)
@@ -18,7 +18,7 @@
                 </div>
                 <div class="fp-setlicense control-group">
                     <label>{{#str}}chooselicense, repository{{/str}}</label>
-                    <select class="form-control"></select>
+                    <select class="custom-select"></select>
                 </div>
             </div>
         </form>
diff --git a/theme/boost/tests/privacy_test.php b/theme/boost/tests/privacy_test.php
new file mode 100644 (file)
index 0000000..6df617f
--- /dev/null
@@ -0,0 +1,78 @@
+<?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/>.
+
+/**
+ * Privacy tests for theme_boost.
+ *
+ * @package    theme_boost
+ * @category   test
+ * @copyright  2018 Adrian Greeve <adriangreeve.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+defined('MOODLE_INTERNAL') || die();
+
+use \theme_boost\privacy\provider;
+
+/**
+ * Unit tests for theme_boost/classes/privacy/policy
+ *
+ * @copyright  2018 Adrian Greeve <adriangreeve.com>
+ * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+class theme_boost_privacy_testcase extends \core_privacy\tests\provider_testcase {
+
+    /**
+     * Test for provider::test_export_user_preferences().
+     */
+    public function test_export_user_preferences() {
+        $this->resetAfterTest();
+
+        // Test setup.
+        $user = $this->getDataGenerator()->create_user();
+        $this->setUser($user);
+
+        // Add a user home page preference for the User.
+        set_user_preference(provider::DRAWER_OPEN_NAV, 'false', $user);
+
+        // Test the user preferences export contains 1 user preference record for the User.
+        provider::export_user_preferences($user->id);
+        $contextuser = context_user::instance($user->id);
+        $writer = \core_privacy\local\request\writer::with_context($contextuser);
+        $this->assertTrue($writer->has_any_data());
+
+        $exportedpreferences = $writer->get_user_preferences('theme_boost');
+        $this->assertCount(1, (array) $exportedpreferences);
+        $this->assertEquals('false', $exportedpreferences->{provider::DRAWER_OPEN_NAV}->value);
+        $this->assertEquals(get_string('privacy:drawernavclosed', 'theme_boost'),
+                $exportedpreferences->{provider::DRAWER_OPEN_NAV}->description);
+
+        // Add a user home page preference for the User.
+        set_user_preference(provider::DRAWER_OPEN_NAV, 'true', $user);
+
+        // Test the user preferences export contains 1 user preference record for the User.
+        provider::export_user_preferences($user->id);
+        $contextuser = context_user::instance($user->id);
+        $writer = \core_privacy\local\request\writer::with_context($contextuser);
+        $this->assertTrue($writer->has_any_data());
+
+        $exportedpreferences = $writer->get_user_preferences('theme_boost');
+        $this->assertCount(1, (array) $exportedpreferences);
+        $this->assertEquals('true', $exportedpreferences->{provider::DRAWER_OPEN_NAV}->value);
+        $this->assertEquals(get_string('privacy:drawernavopen', 'theme_boost'),
+                $exportedpreferences->{provider::DRAWER_OPEN_NAV}->description);
+    }
+}
index 8d4842e..b7a2223 100644 (file)
@@ -25,6 +25,9 @@
 
 
 // Due to lessphp limitations, the following classes must be declared statically without use of a loop.
+.p-0 {
+    padding: 0 !important;
+}
 .p-l-1 {
     padding-left: 1 * @baseFontSize !important;
 }
     padding: 1 * @baseFontSize !important;
 }
 
+.m-0 {
+    margin: 0 !important;
+}
+
 .m-l-1 {
     margin-left: 1 * @baseFontSize !important;
 }
 .bg-faded {
     background-color: @grayLighter;
 }
+
+.w-100 {
+    width: 100%;
+}
index ce2775a..cd03f9b 100644 (file)
@@ -162,7 +162,9 @@ form {
 #page-mod-forum-search .c1 {
     .form-horizontal .controls
 }
-
+.form-inline label:not(.sr-only):not(.accesshide) + select {
+    margin-left: 0.5rem;
+}
 
 .formsettingheading {
     .form-horizontal .help-block
index 4bb1976..32cad6e 100644 (file)
@@ -16726,6 +16726,9 @@ form {
 #page-mod-forum-search .c1:first-child {
   *padding-left: 200px;
 }
+.form-inline label:not(.sr-only):not(.accesshide) + select {
+  margin-left: 0.5rem;
+}
 .formsettingheading {
   margin-bottom: 0;
 }
@@ -21836,6 +21839,9 @@ ul.indented-list {
 .card-block {
   padding: 1.25rem;
 }
+.p-0 {
+  padding: 0 !important;
+}
 .p-l-1 {
   padding-left: 14px !important;
 }
@@ -21859,6 +21865,9 @@ ul.indented-list {
 .p-a-1 {
   padding: 14px !important;
 }
+.m-0 {
+  margin: 0 !important;
+}
 .m-l-1 {
   margin-left: 14px !important;
 }
@@ -22066,3 +22075,6 @@ ul.indented-list {
 .bg-faded {
   background-color: #eee;
 }
+.w-100 {
+  width: 100%;
+}