MDL-65896 admin: add admin setting to show emoji picker
authorRyan Wyllie <ryan@moodle.com>
Fri, 11 Oct 2019 03:01:40 +0000 (11:01 +0800)
committerRyan Wyllie <ryan@moodle.com>
Wed, 23 Oct 2019 02:59:59 +0000 (10:59 +0800)
Added an admin setting to show/hide the emoji picker in messaging
because some versions of MySQL don't have full unicode support so
emojis won't save in the dabase.

If we detect that the site is running an unsupported version of MySQL
then the setting can not be enabled. Instead the admin will see a
message explaining that they will need to upgrade their database
before they can enable the emoji picker.

admin/settings/subsystems.php
lang/en/admin.php
message/amd/build/message_drawer_view_conversation.min.js
message/amd/build/message_drawer_view_conversation.min.js.map
message/amd/src/message_drawer_view_conversation.js
message/classes/helper.php
message/templates/message_drawer_view_conversation_footer_content.mustache

index 597e36b..e31b043 100644 (file)
@@ -51,4 +51,31 @@ if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
 
     $optionalsubsystems->add(new admin_setting_configcheckbox('enableanalytics', new lang_string('enableanalytics', 'admin'),
         new lang_string('configenableanalytics', 'admin'), 1, 1, 0));
+
+
+    $fullunicodesupport = true;
+    if ($DB->get_dbfamily() == 'mysql') {
+        $collation = $DB->get_dbcollation();
+        $collationinfo = explode('_', $collation);
+        $charset = reset($collationinfo);
+
+        if ($charset !== 'utf8') {
+            $fullunicodesupport = false;
+        }
+    }
+
+    if ($fullunicodesupport) {
+        $optionalsubsystems->add(new admin_setting_configcheckbox(
+            'allowemojipicker',
+            new lang_string('allowemojipicker', 'admin'),
+            new lang_string('configallowemojipicker', 'admin'),
+            1
+        ));
+    } else {
+        $optionalsubsystems->add(new admin_setting_description(
+            'allowemojipicker',
+            new lang_string('allowemojipicker', 'admin'),
+            new lang_string('configallowemojipickerincompatible', 'admin')
+        ));
+    }
 }
index 3a51249..5711680 100644 (file)
@@ -53,6 +53,7 @@ $string['allowcoursethemes'] = 'Allow course themes';
 $string['allowediplist'] = 'Allowed IP list';
 $string['allowedemaildomains'] = 'Allowed email domains';
 $string['allowemailaddresses'] = 'Allowed email domains';
+$string['allowemojipicker'] = 'Enable emoji picker';
 $string['allowindexing'] = 'Allow indexing by search engines';
 $string['allowindexing_desc'] = 'This determines whether to allow search engines to index your site. "Everywhere" will allow the search engines to search everywhere including login and signup pages, which means sites with Force Login turned on are still indexed. To avoid the risk of spam involved with the signup page being searchable, use "Everywhere except login and signup pages". "Nowhere" will tell search engines not to index any page. Note this is only a tag in the header of the site. It is up to the search engine to respect the tag.';
 $string['allowindexingeverywhere'] = 'Everywhere';
@@ -153,6 +154,8 @@ $string['configallowcohortthemes'] = 'If you enable this, then themes can be set
 $string['configallowcoursethemes'] = 'If you enable this, then courses will be allowed to set their own themes.  Course themes override all other theme choices (site, user, or session themes)';
 $string['configallowedemaildomains'] = 'List email domains that are allowed to be disclosed in the "From" section of outgoing email. The default of "Empty" will use the No-reply address for all outgoing email. The use of wildcards is allowed e.g. *.example.com will allow emails sent from any subdomain of example.com, but not example.com itself. This will require separate entry.';
 $string['configallowemailaddresses'] = 'To restrict new email addresses to particular domains, list them here separated by spaces. All other domains will be rejected. To allow subdomains, add the domain with a preceding \'.\'. To allow a root domain together with its subdomains, add the domain twice - once with a preceding \'.\' and once without e.g. .ourcollege.edu.au ourcollege.edu.au.';
+$string['configallowemojipicker'] = 'If enabled, the emoji picker will be available within the site';
+$string['configallowemojipickerincompatible'] = 'Your current database configuration does not properly support emojis. In order to enable the emoji picker you will need to <a href="https://docs.moodle.org/37/en/MySQL_full_unicode_support">upgrade your database for full unicode support</a>.';
 $string['configallowguestmymoodle'] = 'If enabled guests can access Dashboard, otherwise guests are redirected to the site front page.';
 $string['configallowobjectembed'] = 'As a default security measure, normal users are not allowed to embed multimedia (like Flash) within texts using explicit EMBED and OBJECT tags in their HTML (although it can still be done safely using the mediaplugins filter).  If you wish to allow these tags then enable this option.';
 $string['configallowoverride'] = 'You can allow people with the roles on the left side to override some of the column roles';
index f3bcd8c..dddf264 100644 (file)
Binary files a/message/amd/build/message_drawer_view_conversation.min.js and b/message/amd/build/message_drawer_view_conversation.min.js differ
index 0713f09..32fe99e 100644 (file)
Binary files a/message/amd/build/message_drawer_view_conversation.min.js.map and b/message/amd/build/message_drawer_view_conversation.min.js.map differ
index 7e3c0da..7efc94f 100644 (file)
@@ -1600,45 +1600,49 @@ function(
 
         AutoRows.init(footer);
 
-        initialiseEmojiAutoComplete(
-            emojiAutoCompleteContainer[0],
-            messageTextArea[0],
-            function(hasSuggestions) {
-                var newState = StateManager.setShowEmojiAutoComplete(viewState, hasSuggestions);
-                render(newState);
-            },
-            function(emoji) {
-                var newState = StateManager.setShowEmojiAutoComplete(viewState, false);
+        if (emojiAutoCompleteContainer.length) {
+            initialiseEmojiAutoComplete(
+                emojiAutoCompleteContainer[0],
+                messageTextArea[0],
+                function(hasSuggestions) {
+                    var newState = StateManager.setShowEmojiAutoComplete(viewState, hasSuggestions);
+                    render(newState);
+                },
+                function(emoji) {
+                    var newState = StateManager.setShowEmojiAutoComplete(viewState, false);
+                    render(newState);
+
+                    messageTextArea.focus();
+                    var cursorPos = messageTextArea.prop('selectionStart');
+                    var currentText = messageTextArea.val();
+                    var textBefore = currentText.substring(0, cursorPos).replace(/\S*$/, '');
+                    var textAfter = currentText.substring(cursorPos).replace(/^\S*/, '');
+
+                    messageTextArea.val(textBefore + emoji + textAfter);
+                    // Set the cursor position to after the inserted emoji.
+                    messageTextArea.prop('selectionStart', textBefore.length + emoji.length);
+                    messageTextArea.prop('selectionEnd', textBefore.length + emoji.length);
+                }
+            );
+        }
+
+        if (emojiPickerElement.length) {
+            initialiseEmojiPicker(emojiPickerElement[0], function(emoji) {
+                var newState = StateManager.setShowEmojiPicker(viewState, !viewState.showEmojiPicker);
                 render(newState);
 
                 messageTextArea.focus();
                 var cursorPos = messageTextArea.prop('selectionStart');
                 var currentText = messageTextArea.val();
-                var textBefore = currentText.substring(0, cursorPos).replace(/\S*$/, '');
-                var textAfter = currentText.substring(cursorPos).replace(/^\S*/, '');
+                var textBefore = currentText.substring(0, cursorPos);
+                var textAfter = currentText.substring(cursorPos, currentText.length);
 
                 messageTextArea.val(textBefore + emoji + textAfter);
                 // Set the cursor position to after the inserted emoji.
-                messageTextArea.prop('selectionStart', textBefore.length + emoji.length);
-                messageTextArea.prop('selectionEnd', textBefore.length + emoji.length);
-            }
-        );
-
-        initialiseEmojiPicker(emojiPickerElement[0], function(emoji) {
-            var newState = StateManager.setShowEmojiPicker(viewState, !viewState.showEmojiPicker);
-            render(newState);
-
-            messageTextArea.focus();
-            var cursorPos = messageTextArea.prop('selectionStart');
-            var currentText = messageTextArea.val();
-            var textBefore = currentText.substring(0, cursorPos);
-            var textAfter = currentText.substring(cursorPos, currentText.length);
-
-            messageTextArea.val(textBefore + emoji + textAfter);
-            // Set the cursor position to after the inserted emoji.
-            messageTextArea.prop('selectionStart', cursorPos + emoji.length);
-            messageTextArea.prop('selectionEnd', cursorPos + emoji.length);
-        });
+                messageTextArea.prop('selectionStart', cursorPos + emoji.length);
+                messageTextArea.prop('selectionEnd', cursorPos + emoji.length);
+            });
+        }
 
         CustomEvents.define(header, [
             CustomEvents.events.activate
index 2116ba3..c6472a4 100644 (file)
@@ -772,7 +772,8 @@ class helper {
                 'messageurl' => $messageurl,
                 'notification' => $notification
             ],
-            'isdrawer' => $isdrawer
+            'isdrawer' => $isdrawer,
+            'showemojipicker' => !empty($CFG->allowemojipicker)
         ];
 
         if ($sendtouser || $conversationid) {
index 683d65a..d786bb9 100644 (file)
 
 }}
 
-<div
-    class="emoji-auto-complete-container w-100 hidden"
-    data-region="emoji-auto-complete-container"
-    aria-live="polite"
-    aria-hidden="true"
->
-</div>
+{{#showemojipicker}}
+    <div
+        class="emoji-auto-complete-container w-100 hidden"
+        data-region="emoji-auto-complete-container"
+        aria-live="polite"
+        aria-hidden="true"
+    >
+    </div>
+{{/showemojipicker}}
 <div class="d-flex mt-1">
     <textarea
         dir="auto"
     ></textarea>
 
     <div class="position-relative d-flex flex-column">
-        <div
-            data-region="emoji-picker-container"
-            class="emoji-picker-container hidden"
-            aria-hidden="true"
-        >
-            {{> core/emoji/picker }}
-        </div>
-        <button
-            class="btn btn-link btn-icon icon-size-3 ml-1"
-            data-action="toggle-emoji-picker"
-        >
-            {{#pix}} e/emoticons, core{{/pix}}
-        </button>
+        {{#showemojipicker}}
+            <div
+                data-region="emoji-picker-container"
+                class="emoji-picker-container hidden"
+                aria-hidden="true"
+            >
+                {{> core/emoji/picker }}
+            </div>
+            <button
+                class="btn btn-link btn-icon icon-size-3 ml-1"
+                data-action="toggle-emoji-picker"
+            >
+                {{#pix}} e/emoticons, core{{/pix}}
+            </button>
+        {{/showemojipicker}}
         <button
             class="btn btn-link btn-icon icon-size-3 ml-1 mt-auto"
             aria-label="{{#str}} sendmessage, core_message {{/str}}"