diff --git a/lib/db/messages.php b/lib/db/messages.php
index d3473bba7e4..3ae3810c3d4 100644
--- a/lib/db/messages.php
+++ b/lib/db/messages.php
@@ -121,7 +121,8 @@ $messageproviders = array (
// Message contact requests.
'messagecontactrequests' => [
'defaults' => [
- 'popup' => MESSAGE_PERMITTED + MESSAGE_DEFAULT_LOGGEDIN + MESSAGE_DEFAULT_LOGGEDOFF,
+ // We don't need to notify in the popup output here because the message drawer
+ // already notifies users of contact requests.
'email' => MESSAGE_PERMITTED + MESSAGE_DEFAULT_LOGGEDOFF,
'airnotifier' => MESSAGE_PERMITTED + MESSAGE_DEFAULT_LOGGEDIN + MESSAGE_DEFAULT_LOGGEDOFF,
]
diff --git a/lib/db/upgrade.php b/lib/db/upgrade.php
index 17190d39855..1833f1c7293 100644
--- a/lib/db/upgrade.php
+++ b/lib/db/upgrade.php
@@ -3431,5 +3431,21 @@ function xmldb_main_upgrade($oldversion) {
upgrade_main_savepoint(true, 2019072200.00);
}
+ if ($oldversion < 2019072500.01) {
+ // Remove the "popup" processor from the list of default processors for the messagecontactrequests notification.
+ $oldloggedinconfig = get_config('message', 'message_provider_moodle_messagecontactrequests_loggedin');
+ $oldloggedoffconfig = get_config('message', 'message_provider_moodle_messagecontactrequests_loggedoff');
+ $newloggedinconfig = implode(',', array_filter(explode(',', $oldloggedinconfig), function($value) {
+ return $value != 'popup';
+ }));
+ $newloggedoffconfig = implode(',', array_filter(explode(',', $oldloggedoffconfig), function($value) {
+ return $value != 'popup';
+ }));
+ set_config('message_provider_moodle_messagecontactrequests_loggedin', $newloggedinconfig, 'message');
+ set_config('message_provider_moodle_messagecontactrequests_loggedoff', $newloggedoffconfig, 'message');
+
+ upgrade_main_savepoint(true, 2019072500.01);
+ }
+
return true;
}
diff --git a/message/amd/build/message_drawer.min.js b/message/amd/build/message_drawer.min.js
index 00f658e1dda..14cd5ae3e59 100644
--- a/message/amd/build/message_drawer.min.js
+++ b/message/amd/build/message_drawer.min.js
@@ -1,2 +1,2 @@
-define ("core_message/message_drawer",["jquery","core/custom_interaction_events","core/pubsub","core_message/message_drawer_view_contact","core_message/message_drawer_view_contacts","core_message/message_drawer_view_conversation","core_message/message_drawer_view_group_info","core_message/message_drawer_view_overview","core_message/message_drawer_view_search","core_message/message_drawer_view_settings","core_message/message_drawer_router","core_message/message_drawer_routes","core_message/message_drawer_events"],function(a,b,c,d,e,f,g,h,i,j,k,l,m){var n={PANEL_BODY_CONTAINER:"[data-region=\"panel-body-container\"]",PANEL_HEADER_CONTAINER:"[data-region=\"panel-header-container\"]",VIEW_CONTACT:"[data-region=\"view-contact\"]",VIEW_CONTACTS:"[data-region=\"view-contacts\"]",VIEW_CONVERSATION:"[data-region=\"view-conversation\"]",VIEW_GROUP_INFO:"[data-region=\"view-group-info\"]",VIEW_OVERVIEW:"[data-region=\"view-overview\"]",VIEW_SEARCH:"[data-region=\"view-search\"]",VIEW_SETTINGS:"[data-region=\"view-settings\"]",ROUTES:"[data-route]",ROUTES_BACK:"[data-route-back]",HEADER_CONTAINER:"[data-region=\"header-container\"]",BODY_CONTAINER:"[data-region=\"body-container\"]",FOOTER_CONTAINER:"[data-region=\"footer-container\"]"},o=function(a,b,c){var d=b.find(n.HEADER_CONTAINER).find(c);if(!d.length){d=b.find(n.PANEL_HEADER_CONTAINER).find(c)}var e=b.find(n.BODY_CONTAINER).find(c);if(!e.length){e=b.find(n.PANEL_BODY_CONTAINER).find(c)}var f=b.find(n.FOOTER_CONTAINER).find(c);return[a,d.length?d:null,e.length?e:null,f.length?f:null]},p=[[l.VIEW_CONTACT,n.VIEW_CONTACT,d.show,d.description],[l.VIEW_CONTACTS,n.VIEW_CONTACTS,e.show,e.description],[l.VIEW_CONVERSATION,n.VIEW_CONVERSATION,f.show,f.description],[l.VIEW_GROUP_INFO,n.VIEW_GROUP_INFO,g.show,g.description],[l.VIEW_OVERVIEW,n.VIEW_OVERVIEW,h.show,h.description],[l.VIEW_SEARCH,n.VIEW_SEARCH,i.show,i.description],[l.VIEW_SETTINGS,n.VIEW_SETTINGS,j.show,j.description]],q=function(a,b){p.forEach(function(c){k.add(a,c[0],o(a,b,c[1]),c[2],c[3])})},r=function(a,b){if(!b.attr("data-shown")){k.go(a,l.VIEW_OVERVIEW);b.attr("data-shown",!0)}b.removeClass("hidden");b.attr("aria-expanded",!0);b.attr("aria-hidden",!1)},s=function(a){a.addClass("hidden");a.attr("aria-expanded",!1);a.attr("aria-hidden",!0)},t=function(a){return!a.hasClass("hidden")},u=function(d,e,f){b.define(e,[b.events.activate]);var g=/^data-route-param-?(\d*)$/;e.on(b.events.activate,n.ROUTES,function(b,c){for(var e=a(b.target).closest(n.ROUTES),f=e.attr("data-route"),h=[],j=0;j.\n\n/**\n * Controls the message drawer.\n *\n * @module core_message/message_drawer\n * @copyright 2018 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(\n[\n 'jquery',\n 'core/custom_interaction_events',\n 'core/pubsub',\n 'core_message/message_drawer_view_contact',\n 'core_message/message_drawer_view_contacts',\n 'core_message/message_drawer_view_conversation',\n 'core_message/message_drawer_view_group_info',\n 'core_message/message_drawer_view_overview',\n 'core_message/message_drawer_view_search',\n 'core_message/message_drawer_view_settings',\n 'core_message/message_drawer_router',\n 'core_message/message_drawer_routes',\n 'core_message/message_drawer_events'\n],\nfunction(\n $,\n CustomEvents,\n PubSub,\n ViewContact,\n ViewContacts,\n ViewConversation,\n ViewGroupInfo,\n ViewOverview,\n ViewSearch,\n ViewSettings,\n Router,\n Routes,\n Events\n) {\n\n var SELECTORS = {\n PANEL_BODY_CONTAINER: '[data-region=\"panel-body-container\"]',\n PANEL_HEADER_CONTAINER: '[data-region=\"panel-header-container\"]',\n VIEW_CONTACT: '[data-region=\"view-contact\"]',\n VIEW_CONTACTS: '[data-region=\"view-contacts\"]',\n VIEW_CONVERSATION: '[data-region=\"view-conversation\"]',\n VIEW_GROUP_INFO: '[data-region=\"view-group-info\"]',\n VIEW_OVERVIEW: '[data-region=\"view-overview\"]',\n VIEW_SEARCH: '[data-region=\"view-search\"]',\n VIEW_SETTINGS: '[data-region=\"view-settings\"]',\n ROUTES: '[data-route]',\n ROUTES_BACK: '[data-route-back]',\n HEADER_CONTAINER: '[data-region=\"header-container\"]',\n BODY_CONTAINER: '[data-region=\"body-container\"]',\n FOOTER_CONTAINER: '[data-region=\"footer-container\"]',\n };\n\n /**\n * Get elements for route.\n *\n * @param {String} namespace Unique identifier for the Routes\n * @param {Object} root The message drawer container.\n * @param {string} selector The route container.\n *\n * @return {array} elements Found route container objects.\n */\n var getParametersForRoute = function(namespace, root, selector) {\n\n var header = root.find(SELECTORS.HEADER_CONTAINER).find(selector);\n if (!header.length) {\n header = root.find(SELECTORS.PANEL_HEADER_CONTAINER).find(selector);\n }\n var body = root.find(SELECTORS.BODY_CONTAINER).find(selector);\n if (!body.length) {\n body = root.find(SELECTORS.PANEL_BODY_CONTAINER).find(selector);\n }\n var footer = root.find(SELECTORS.FOOTER_CONTAINER).find(selector);\n\n return [\n namespace,\n header.length ? header : null,\n body.length ? body : null,\n footer.length ? footer : null\n ];\n };\n\n var routes = [\n [Routes.VIEW_CONTACT, SELECTORS.VIEW_CONTACT, ViewContact.show, ViewContact.description],\n [Routes.VIEW_CONTACTS, SELECTORS.VIEW_CONTACTS, ViewContacts.show, ViewContacts.description],\n [Routes.VIEW_CONVERSATION, SELECTORS.VIEW_CONVERSATION, ViewConversation.show, ViewConversation.description],\n [Routes.VIEW_GROUP_INFO, SELECTORS.VIEW_GROUP_INFO, ViewGroupInfo.show, ViewGroupInfo.description],\n [Routes.VIEW_OVERVIEW, SELECTORS.VIEW_OVERVIEW, ViewOverview.show, ViewOverview.description],\n [Routes.VIEW_SEARCH, SELECTORS.VIEW_SEARCH, ViewSearch.show, ViewSearch.description],\n [Routes.VIEW_SETTINGS, SELECTORS.VIEW_SETTINGS, ViewSettings.show, ViewSettings.description]\n ];\n\n /**\n * Create routes.\n *\n * @param {String} namespace Unique identifier for the Routes\n * @param {Object} root The message drawer container.\n */\n var createRoutes = function(namespace, root) {\n routes.forEach(function(route) {\n Router.add(namespace, route[0], getParametersForRoute(namespace, root, route[1]), route[2], route[3]);\n });\n };\n\n /**\n * Show the message drawer.\n *\n * @param {string} namespace The route namespace.\n * @param {Object} root The message drawer container.\n */\n var show = function(namespace, root) {\n if (!root.attr('data-shown')) {\n Router.go(namespace, Routes.VIEW_OVERVIEW);\n root.attr('data-shown', true);\n }\n\n root.removeClass('hidden');\n root.attr('aria-expanded', true);\n root.attr('aria-hidden', false);\n };\n\n /**\n * Hide the message drawer.\n *\n * @param {Object} root The message drawer container.\n */\n var hide = function(root) {\n root.addClass('hidden');\n root.attr('aria-expanded', false);\n root.attr('aria-hidden', true);\n };\n\n /**\n * Check if the drawer is visible.\n *\n * @param {Object} root The message drawer container.\n * @return {bool}\n */\n var isVisible = function(root) {\n return !root.hasClass('hidden');\n };\n\n /**\n * Listen to and handle events for routing, showing and hiding the message drawer.\n *\n * @param {string} namespace The route namespace.\n * @param {Object} root The message drawer container.\n * @param {bool} alwaysVisible Is this messaging app always shown?\n */\n var registerEventListeners = function(namespace, root, alwaysVisible) {\n CustomEvents.define(root, [CustomEvents.events.activate]);\n var paramRegex = /^data-route-param-?(\\d*)$/;\n\n root.on(CustomEvents.events.activate, SELECTORS.ROUTES, function(e, data) {\n var element = $(e.target).closest(SELECTORS.ROUTES);\n var route = element.attr('data-route');\n var attributes = [];\n\n for (var i = 0; i < element[0].attributes.length; i++) {\n attributes.push(element[0].attributes[i]);\n }\n\n var paramAttributes = attributes.filter(function(attribute) {\n var name = attribute.nodeName;\n var match = paramRegex.test(name);\n return match;\n });\n paramAttributes.sort(function(a, b) {\n var aParts = paramRegex.exec(a.nodeName);\n var bParts = paramRegex.exec(b.nodeName);\n var aIndex = aParts.length > 1 ? aParts[1] : 0;\n var bIndex = bParts.length > 1 ? bParts[1] : 0;\n\n if (aIndex < bIndex) {\n return -1;\n } else if (bIndex < aIndex) {\n return 1;\n } else {\n return 0;\n }\n });\n\n var params = paramAttributes.map(function(attribute) {\n return attribute.nodeValue;\n });\n\n var routeParams = [namespace, route].concat(params);\n\n Router.go.apply(null, routeParams);\n\n data.originalEvent.preventDefault();\n });\n\n root.on(CustomEvents.events.activate, SELECTORS.ROUTES_BACK, function(e, data) {\n Router.back(namespace);\n\n data.originalEvent.preventDefault();\n });\n\n if (!alwaysVisible) {\n PubSub.subscribe(Events.SHOW, function() {\n show(namespace, root);\n });\n\n PubSub.subscribe(Events.HIDE, function() {\n hide(root);\n });\n\n PubSub.subscribe(Events.TOGGLE_VISIBILITY, function() {\n if (isVisible(root)) {\n hide(root);\n } else {\n show(namespace, root);\n }\n });\n }\n\n PubSub.subscribe(Events.SHOW_CONVERSATION, function(conversationId) {\n show(namespace, root);\n Router.go(namespace, Routes.VIEW_CONVERSATION, conversationId);\n });\n\n PubSub.subscribe(Events.CREATE_CONVERSATION_WITH_USER, function(userId) {\n show(namespace, root);\n Router.go(namespace, Routes.VIEW_CONVERSATION, null, 'create', userId);\n });\n\n PubSub.subscribe(Events.SHOW_SETTINGS, function() {\n show(namespace, root);\n Router.go(namespace, Routes.VIEW_SETTINGS);\n });\n\n PubSub.subscribe(Events.PREFERENCES_UPDATED, function(preferences) {\n var filteredPreferences = preferences.filter(function(preference) {\n return preference.type == 'message_entertosend';\n });\n var enterToSendPreference = filteredPreferences.length ? filteredPreferences[0] : null;\n\n if (enterToSendPreference) {\n var viewConversationFooter = root.find(SELECTORS.FOOTER_CONTAINER).find(SELECTORS.VIEW_CONVERSATION);\n viewConversationFooter.attr('data-enter-to-send', enterToSendPreference.value);\n }\n });\n };\n\n /**\n * Initialise the message drawer.\n *\n * @param {Object} root The message drawer container.\n * @param {String} uniqueId Unique identifier for the Routes\n * @param {bool} alwaysVisible Should we show the app now, or wait for the user?\n * @param {int} sendToUser Should we message someone now?\n * @param {int} conversationId The value of the conversation id, null if none\n */\n var init = function(root, uniqueId, alwaysVisible, sendToUser, conversationId) {\n root = $(root);\n createRoutes(uniqueId, root);\n registerEventListeners(uniqueId, root, alwaysVisible);\n if (alwaysVisible) {\n show(uniqueId, root);\n // Are we sending to a specific user?\n if (sendToUser) {\n // Check if a conversation already exists, if not, create one.\n if (conversationId) {\n Router.go(uniqueId, Routes.VIEW_CONVERSATION, conversationId);\n } else {\n Router.go(uniqueId, Routes.VIEW_CONVERSATION, null, 'create', sendToUser);\n }\n } else if (conversationId) { // We aren't sending to a specific user, but to a group conversation.\n Router.go(uniqueId, Routes.VIEW_CONVERSATION, conversationId);\n }\n }\n };\n\n return {\n init: init,\n };\n});\n"],"file":"message_drawer.min.js"}
\ No newline at end of file
+{"version":3,"sources":["../src/message_drawer.js"],"names":["define","$","CustomEvents","PubSub","ViewContact","ViewContacts","ViewConversation","ViewGroupInfo","ViewOverview","ViewSearch","ViewSettings","Router","Routes","Events","SELECTORS","PANEL_BODY_CONTAINER","PANEL_HEADER_CONTAINER","VIEW_CONTACT","VIEW_CONTACTS","VIEW_CONVERSATION","VIEW_GROUP_INFO","VIEW_OVERVIEW","VIEW_SEARCH","VIEW_SETTINGS","ROUTES","ROUTES_BACK","HEADER_CONTAINER","BODY_CONTAINER","FOOTER_CONTAINER","getParametersForRoute","namespace","root","selector","header","find","length","body","footer","routes","show","description","createRoutes","forEach","route","add","attr","go","removeClass","hide","addClass","isVisible","hasClass","registerEventListeners","alwaysVisible","events","activate","paramRegex","on","e","data","element","target","closest","attributes","i","push","paramAttributes","filter","attribute","name","nodeName","match","test","sort","a","b","aParts","exec","bParts","aIndex","bIndex","params","map","nodeValue","routeParams","concat","apply","originalEvent","preventDefault","back","subscribe","SHOW","HIDE","TOGGLE_VISIBILITY","SHOW_CONVERSATION","conversationId","CREATE_CONVERSATION_WITH_USER","userId","SHOW_SETTINGS","PREFERENCES_UPDATED","preferences","filteredPreferences","preference","type","enterToSendPreference","viewConversationFooter","value","init","uniqueId","path"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Controls the message drawer.\n *\n * @module core_message/message_drawer\n * @copyright 2018 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(\n[\n 'jquery',\n 'core/custom_interaction_events',\n 'core/pubsub',\n 'core_message/message_drawer_view_contact',\n 'core_message/message_drawer_view_contacts',\n 'core_message/message_drawer_view_conversation',\n 'core_message/message_drawer_view_group_info',\n 'core_message/message_drawer_view_overview',\n 'core_message/message_drawer_view_search',\n 'core_message/message_drawer_view_settings',\n 'core_message/message_drawer_router',\n 'core_message/message_drawer_routes',\n 'core_message/message_drawer_events'\n],\nfunction(\n $,\n CustomEvents,\n PubSub,\n ViewContact,\n ViewContacts,\n ViewConversation,\n ViewGroupInfo,\n ViewOverview,\n ViewSearch,\n ViewSettings,\n Router,\n Routes,\n Events\n) {\n\n var SELECTORS = {\n PANEL_BODY_CONTAINER: '[data-region=\"panel-body-container\"]',\n PANEL_HEADER_CONTAINER: '[data-region=\"panel-header-container\"]',\n VIEW_CONTACT: '[data-region=\"view-contact\"]',\n VIEW_CONTACTS: '[data-region=\"view-contacts\"]',\n VIEW_CONVERSATION: '[data-region=\"view-conversation\"]',\n VIEW_GROUP_INFO: '[data-region=\"view-group-info\"]',\n VIEW_OVERVIEW: '[data-region=\"view-overview\"]',\n VIEW_SEARCH: '[data-region=\"view-search\"]',\n VIEW_SETTINGS: '[data-region=\"view-settings\"]',\n ROUTES: '[data-route]',\n ROUTES_BACK: '[data-route-back]',\n HEADER_CONTAINER: '[data-region=\"header-container\"]',\n BODY_CONTAINER: '[data-region=\"body-container\"]',\n FOOTER_CONTAINER: '[data-region=\"footer-container\"]',\n };\n\n /**\n * Get elements for route.\n *\n * @param {String} namespace Unique identifier for the Routes\n * @param {Object} root The message drawer container.\n * @param {string} selector The route container.\n *\n * @return {array} elements Found route container objects.\n */\n var getParametersForRoute = function(namespace, root, selector) {\n\n var header = root.find(SELECTORS.HEADER_CONTAINER).find(selector);\n if (!header.length) {\n header = root.find(SELECTORS.PANEL_HEADER_CONTAINER).find(selector);\n }\n var body = root.find(SELECTORS.BODY_CONTAINER).find(selector);\n if (!body.length) {\n body = root.find(SELECTORS.PANEL_BODY_CONTAINER).find(selector);\n }\n var footer = root.find(SELECTORS.FOOTER_CONTAINER).find(selector);\n\n return [\n namespace,\n header.length ? header : null,\n body.length ? body : null,\n footer.length ? footer : null\n ];\n };\n\n var routes = [\n [Routes.VIEW_CONTACT, SELECTORS.VIEW_CONTACT, ViewContact.show, ViewContact.description],\n [Routes.VIEW_CONTACTS, SELECTORS.VIEW_CONTACTS, ViewContacts.show, ViewContacts.description],\n [Routes.VIEW_CONVERSATION, SELECTORS.VIEW_CONVERSATION, ViewConversation.show, ViewConversation.description],\n [Routes.VIEW_GROUP_INFO, SELECTORS.VIEW_GROUP_INFO, ViewGroupInfo.show, ViewGroupInfo.description],\n [Routes.VIEW_OVERVIEW, SELECTORS.VIEW_OVERVIEW, ViewOverview.show, ViewOverview.description],\n [Routes.VIEW_SEARCH, SELECTORS.VIEW_SEARCH, ViewSearch.show, ViewSearch.description],\n [Routes.VIEW_SETTINGS, SELECTORS.VIEW_SETTINGS, ViewSettings.show, ViewSettings.description]\n ];\n\n /**\n * Create routes.\n *\n * @param {String} namespace Unique identifier for the Routes\n * @param {Object} root The message drawer container.\n */\n var createRoutes = function(namespace, root) {\n routes.forEach(function(route) {\n Router.add(namespace, route[0], getParametersForRoute(namespace, root, route[1]), route[2], route[3]);\n });\n };\n\n /**\n * Show the message drawer.\n *\n * @param {string} namespace The route namespace.\n * @param {Object} root The message drawer container.\n */\n var show = function(namespace, root) {\n if (!root.attr('data-shown')) {\n Router.go(namespace, Routes.VIEW_OVERVIEW);\n root.attr('data-shown', true);\n }\n\n root.removeClass('hidden');\n root.attr('aria-expanded', true);\n root.attr('aria-hidden', false);\n };\n\n /**\n * Hide the message drawer.\n *\n * @param {Object} root The message drawer container.\n */\n var hide = function(root) {\n root.addClass('hidden');\n root.attr('aria-expanded', false);\n root.attr('aria-hidden', true);\n };\n\n /**\n * Check if the drawer is visible.\n *\n * @param {Object} root The message drawer container.\n * @return {bool}\n */\n var isVisible = function(root) {\n return !root.hasClass('hidden');\n };\n\n /**\n * Listen to and handle events for routing, showing and hiding the message drawer.\n *\n * @param {string} namespace The route namespace.\n * @param {Object} root The message drawer container.\n * @param {bool} alwaysVisible Is this messaging app always shown?\n */\n var registerEventListeners = function(namespace, root, alwaysVisible) {\n CustomEvents.define(root, [CustomEvents.events.activate]);\n var paramRegex = /^data-route-param-?(\\d*)$/;\n\n root.on(CustomEvents.events.activate, SELECTORS.ROUTES, function(e, data) {\n var element = $(e.target).closest(SELECTORS.ROUTES);\n var route = element.attr('data-route');\n var attributes = [];\n\n for (var i = 0; i < element[0].attributes.length; i++) {\n attributes.push(element[0].attributes[i]);\n }\n\n var paramAttributes = attributes.filter(function(attribute) {\n var name = attribute.nodeName;\n var match = paramRegex.test(name);\n return match;\n });\n paramAttributes.sort(function(a, b) {\n var aParts = paramRegex.exec(a.nodeName);\n var bParts = paramRegex.exec(b.nodeName);\n var aIndex = aParts.length > 1 ? aParts[1] : 0;\n var bIndex = bParts.length > 1 ? bParts[1] : 0;\n\n if (aIndex < bIndex) {\n return -1;\n } else if (bIndex < aIndex) {\n return 1;\n } else {\n return 0;\n }\n });\n\n var params = paramAttributes.map(function(attribute) {\n return attribute.nodeValue;\n });\n\n var routeParams = [namespace, route].concat(params);\n\n Router.go.apply(null, routeParams);\n\n data.originalEvent.preventDefault();\n });\n\n root.on(CustomEvents.events.activate, SELECTORS.ROUTES_BACK, function(e, data) {\n Router.back(namespace);\n\n data.originalEvent.preventDefault();\n });\n\n if (!alwaysVisible) {\n PubSub.subscribe(Events.SHOW, function() {\n show(namespace, root);\n });\n\n PubSub.subscribe(Events.HIDE, function() {\n hide(root);\n });\n\n PubSub.subscribe(Events.TOGGLE_VISIBILITY, function() {\n if (isVisible(root)) {\n hide(root);\n } else {\n show(namespace, root);\n }\n });\n }\n\n PubSub.subscribe(Events.SHOW_CONVERSATION, function(conversationId) {\n show(namespace, root);\n Router.go(namespace, Routes.VIEW_CONVERSATION, conversationId);\n });\n\n PubSub.subscribe(Events.CREATE_CONVERSATION_WITH_USER, function(userId) {\n show(namespace, root);\n Router.go(namespace, Routes.VIEW_CONVERSATION, null, 'create', userId);\n });\n\n PubSub.subscribe(Events.SHOW_SETTINGS, function() {\n show(namespace, root);\n Router.go(namespace, Routes.VIEW_SETTINGS);\n });\n\n PubSub.subscribe(Events.PREFERENCES_UPDATED, function(preferences) {\n var filteredPreferences = preferences.filter(function(preference) {\n return preference.type == 'message_entertosend';\n });\n var enterToSendPreference = filteredPreferences.length ? filteredPreferences[0] : null;\n\n if (enterToSendPreference) {\n var viewConversationFooter = root.find(SELECTORS.FOOTER_CONTAINER).find(SELECTORS.VIEW_CONVERSATION);\n viewConversationFooter.attr('data-enter-to-send', enterToSendPreference.value);\n }\n });\n };\n\n /**\n * Initialise the message drawer.\n *\n * @param {Object} root The message drawer container.\n * @param {String} uniqueId Unique identifier for the Routes\n * @param {bool} alwaysVisible Should we show the app now, or wait for the user?\n * @param {int} sendToUser Should we message someone now?\n * @param {int} conversationId The value of the conversation id, null if none\n */\n var init = function(root, uniqueId, alwaysVisible, route) {\n root = $(root);\n createRoutes(uniqueId, root);\n registerEventListeners(uniqueId, root, alwaysVisible);\n\n if (alwaysVisible) {\n show(uniqueId, root);\n\n if (route) {\n var routeParams = route.params || [];\n routeParams = [uniqueId, route.path].concat(routeParams);\n Router.go.apply(null, routeParams);\n }\n }\n };\n\n return {\n init: init,\n };\n});\n"],"file":"message_drawer.min.js"}
\ No newline at end of file
diff --git a/message/amd/build/message_drawer_view_contacts.min.js b/message/amd/build/message_drawer_view_contacts.min.js
index 777c6e18251..67936f61f83 100644
--- a/message/amd/build/message_drawer_view_contacts.min.js
+++ b/message/amd/build/message_drawer_view_contacts.min.js
@@ -1,2 +1,2 @@
-define ("core_message/message_drawer_view_contacts",["jquery","core/pubsub","core/str","core_message/message_drawer_events","core_message/message_drawer_view_contacts_section_contacts","core_message/message_drawer_view_contacts_section_requests"],function(a,b,c,d,e,f){var g={ACTION_SHOW_CONTACTS_SECTION:"[data-action=\"show-contacts-section\"]",ACTION_SHOW_REQUESTS_SECTION:"[data-action=\"show-requests-section\"]",CONTACT_REQUEST_COUNT:"[data-region=\"contact-request-count\"]",CONTACTS_SECTION_CONTAINER:"[data-section=\"contacts\"]",REQUESTS_SECTION_CONTAINER:"[data-section=\"requests\"]"},h=function(a){return a.find(g.CONTACTS_SECTION_CONTAINER)},i=function(a){return a.find(g.REQUESTS_SECTION_CONTAINER)},j=function(a){return a.hasClass("active")},k=function(a){return function(){var b=a.find(g.CONTACT_REQUEST_COUNT),c=parseInt(b.text(),10);c=isNaN(c)?0:c-1;if(0>=c){b.addClass("hidden")}else{b.text(c)}}},l=function(a){var c=h(a),j=i(a),l=a.find(g.ACTION_SHOW_CONTACTS_SECTION),m=a.find(g.ACTION_SHOW_REQUESTS_SECTION);l.on("show.bs.tab",function(){e.show(c)});m.on("show.bs.tab",function(){f.show(j)});b.subscribe(d.CONTACT_REQUEST_ACCEPTED,k(a));b.subscribe(d.CONTACT_REQUEST_DECLINED,k(a))};return{show:function show(b,c,d){d=a(d);if(!d.attr("data-contacts-init")){l(d);d.attr("data-contacts-init",!0)}var g=h(d),k=i(d);if(j(g)){e.show(g)}else{f.show(k)}return a.Deferred().resolve().promise()},description:function description(){return c.get_string("messagedrawerviewcontacts","core_message")}}});
+define ("core_message/message_drawer_view_contacts",["jquery","core/pubsub","core/str","core_message/message_drawer_events","core_message/message_drawer_view_contacts_section_contacts","core_message/message_drawer_view_contacts_section_requests"],function(a,b,c,d,e,f){var g={ACTION_SHOW_CONTACTS_SECTION:"[data-action=\"show-contacts-section\"]",ACTION_SHOW_REQUESTS_SECTION:"[data-action=\"show-requests-section\"]",CONTACT_REQUEST_COUNT:"[data-region=\"contact-request-count\"]",CONTACTS_SECTION_CONTAINER:"[data-section=\"contacts\"]",REQUESTS_SECTION_CONTAINER:"[data-section=\"requests\"]"},h=function(a){return a.find(g.CONTACTS_SECTION_CONTAINER)},i=function(a){return a.find(g.REQUESTS_SECTION_CONTAINER)},j=function(a){return a.find(g.ACTION_SHOW_CONTACTS_SECTION)},k=function(a){return a.find(g.ACTION_SHOW_REQUESTS_SECTION)},l=function(a){return a.hasClass("active")},m=function(a){return function(){var b=a.find(g.CONTACT_REQUEST_COUNT),c=parseInt(b.text(),10);c=isNaN(c)?0:c-1;if(0>=c){b.addClass("hidden")}else{b.text(c)}}},n=function(a){var c=h(a),g=i(a),l=j(a),n=k(a);l.on("show.bs.tab",function(){e.show(c)});n.on("show.bs.tab",function(){f.show(g)});b.subscribe(d.CONTACT_REQUEST_ACCEPTED,m(a));b.subscribe(d.CONTACT_REQUEST_DECLINED,m(a))};return{show:function show(b,c,d,g,m){d=a(d);if(!d.attr("data-contacts-init")){n(d);d.attr("data-contacts-init",!0)}var o=h(d),p=i(d);if(m){var q=j(d),r=k(d);if("requests"==m){q.removeClass("active");o.removeClass("show active");r.addClass("active");p.addClass("show active")}else{r.removeClass("active");p.removeClass("show active");q.addClass("active");o.addClass("show active")}}if(l(o)){e.show(o)}else{f.show(p)}return a.Deferred().resolve().promise()},description:function description(){return c.get_string("messagedrawerviewcontacts","core_message")}}});
//# sourceMappingURL=message_drawer_view_contacts.min.js.map
diff --git a/message/amd/build/message_drawer_view_contacts.min.js.map b/message/amd/build/message_drawer_view_contacts.min.js.map
index 1708a480418..7aa57bdf3e5 100644
--- a/message/amd/build/message_drawer_view_contacts.min.js.map
+++ b/message/amd/build/message_drawer_view_contacts.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["../src/message_drawer_view_contacts.js"],"names":["define","$","PubSub","Str","MessageDrawerEvents","ContactsSection","RequestsSection","SELECTORS","ACTION_SHOW_CONTACTS_SECTION","ACTION_SHOW_REQUESTS_SECTION","CONTACT_REQUEST_COUNT","CONTACTS_SECTION_CONTAINER","REQUESTS_SECTION_CONTAINER","getContactsSectionContainer","body","find","getRequestsSectionContainer","isSectionVisible","sectionRoot","hasClass","decrementContactRequestCount","countContainer","count","parseInt","text","isNaN","addClass","registerEventListeners","contactsSection","requestsSection","showContactsAction","showRequestsAction","on","show","subscribe","CONTACT_REQUEST_ACCEPTED","CONTACT_REQUEST_DECLINED","namespace","header","attr","Deferred","resolve","promise","description","get_string"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Controls the contacts page of the message drawer.\n *\n * @module core_message/message_drawer_view_contacts\n * @copyright 2018 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(\n[\n 'jquery',\n 'core/pubsub',\n 'core/str',\n 'core_message/message_drawer_events',\n 'core_message/message_drawer_view_contacts_section_contacts',\n 'core_message/message_drawer_view_contacts_section_requests'\n],\nfunction(\n $,\n PubSub,\n Str,\n MessageDrawerEvents,\n ContactsSection,\n RequestsSection\n) {\n\n var SELECTORS = {\n ACTION_SHOW_CONTACTS_SECTION: '[data-action=\"show-contacts-section\"]',\n ACTION_SHOW_REQUESTS_SECTION: '[data-action=\"show-requests-section\"]',\n CONTACT_REQUEST_COUNT: '[data-region=\"contact-request-count\"]',\n CONTACTS_SECTION_CONTAINER: '[data-section=\"contacts\"]',\n REQUESTS_SECTION_CONTAINER: '[data-section=\"requests\"]',\n };\n\n /**\n * Get the container element for the contacts section.\n *\n * @param {Object} body Contacts page body element.\n * @return {Object}\n */\n var getContactsSectionContainer = function(body) {\n return body.find(SELECTORS.CONTACTS_SECTION_CONTAINER);\n };\n\n /**\n * Get the container element for the requests section.\n *\n * @param {Object} body Contacts page body element.\n * @return {Object}\n */\n var getRequestsSectionContainer = function(body) {\n return body.find(SELECTORS.REQUESTS_SECTION_CONTAINER);\n };\n\n /**\n * Check if the given section is visible.\n *\n * @param {Object} sectionRoot The root element for the section\n * @return {Bool}\n */\n var isSectionVisible = function(sectionRoot) {\n return sectionRoot.hasClass('active');\n };\n\n /**\n * Decrement the contact request count. If the count is zero or below then\n * hide the count.\n *\n * @param {Object} body Conversation body container element.\n * @return {Function} A function to handle decrementing the count.\n */\n var decrementContactRequestCount = function(body) {\n return function() {\n var countContainer = body.find(SELECTORS.CONTACT_REQUEST_COUNT);\n var count = parseInt(countContainer.text(), 10);\n count = isNaN(count) ? 0 : count - 1;\n\n if (count <= 0) {\n countContainer.addClass('hidden');\n } else {\n countContainer.text(count);\n }\n };\n };\n\n /**\n * Listen to and handle events for contacts.\n *\n * @param {Object} body Contacts body container element.\n */\n var registerEventListeners = function(body) {\n var contactsSection = getContactsSectionContainer(body);\n var requestsSection = getRequestsSectionContainer(body);\n var showContactsAction = body.find(SELECTORS.ACTION_SHOW_CONTACTS_SECTION);\n var showRequestsAction = body.find(SELECTORS.ACTION_SHOW_REQUESTS_SECTION);\n\n showContactsAction.on('show.bs.tab', function() {\n ContactsSection.show(contactsSection);\n });\n\n showRequestsAction.on('show.bs.tab', function() {\n RequestsSection.show(requestsSection);\n });\n\n PubSub.subscribe(MessageDrawerEvents.CONTACT_REQUEST_ACCEPTED, decrementContactRequestCount(body));\n PubSub.subscribe(MessageDrawerEvents.CONTACT_REQUEST_DECLINED, decrementContactRequestCount(body));\n };\n\n /**\n * Setup the contact page.\n *\n * @param {string} namespace The route namespace.\n * @param {Object} header Contacts header container element.\n * @param {Object} body Contacts body container element.\n * @return {Object} jQuery promise\n */\n var show = function(namespace, header, body) {\n body = $(body);\n\n if (!body.attr('data-contacts-init')) {\n registerEventListeners(body);\n body.attr('data-contacts-init', true);\n }\n\n var contactsSection = getContactsSectionContainer(body);\n var requestsSection = getRequestsSectionContainer(body);\n\n if (isSectionVisible(contactsSection)) {\n ContactsSection.show(contactsSection);\n } else {\n RequestsSection.show(requestsSection);\n }\n\n return $.Deferred().resolve().promise();\n };\n\n /**\n * String describing this page used for aria-labels.\n *\n * @return {Object} jQuery promise\n */\n var description = function() {\n return Str.get_string('messagedrawerviewcontacts', 'core_message');\n };\n\n return {\n show: show,\n description: description\n };\n});\n"],"file":"message_drawer_view_contacts.min.js"}
\ No newline at end of file
+{"version":3,"sources":["../src/message_drawer_view_contacts.js"],"names":["define","$","PubSub","Str","MessageDrawerEvents","ContactsSection","RequestsSection","SELECTORS","ACTION_SHOW_CONTACTS_SECTION","ACTION_SHOW_REQUESTS_SECTION","CONTACT_REQUEST_COUNT","CONTACTS_SECTION_CONTAINER","REQUESTS_SECTION_CONTAINER","getContactsSectionContainer","body","find","getRequestsSectionContainer","getShowContactsAction","getShowRequestsAction","isSectionVisible","sectionRoot","hasClass","decrementContactRequestCount","countContainer","count","parseInt","text","isNaN","addClass","registerEventListeners","contactsSection","requestsSection","showContactsAction","showRequestsAction","on","show","subscribe","CONTACT_REQUEST_ACCEPTED","CONTACT_REQUEST_DECLINED","namespace","header","footer","tab","attr","removeClass","Deferred","resolve","promise","description","get_string"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Controls the contacts page of the message drawer.\n *\n * @module core_message/message_drawer_view_contacts\n * @copyright 2018 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(\n[\n 'jquery',\n 'core/pubsub',\n 'core/str',\n 'core_message/message_drawer_events',\n 'core_message/message_drawer_view_contacts_section_contacts',\n 'core_message/message_drawer_view_contacts_section_requests'\n],\nfunction(\n $,\n PubSub,\n Str,\n MessageDrawerEvents,\n ContactsSection,\n RequestsSection\n) {\n\n var SELECTORS = {\n ACTION_SHOW_CONTACTS_SECTION: '[data-action=\"show-contacts-section\"]',\n ACTION_SHOW_REQUESTS_SECTION: '[data-action=\"show-requests-section\"]',\n CONTACT_REQUEST_COUNT: '[data-region=\"contact-request-count\"]',\n CONTACTS_SECTION_CONTAINER: '[data-section=\"contacts\"]',\n REQUESTS_SECTION_CONTAINER: '[data-section=\"requests\"]',\n };\n\n /**\n * Get the container element for the contacts section.\n *\n * @param {Object} body Contacts page body element.\n * @return {Object}\n */\n var getContactsSectionContainer = function(body) {\n return body.find(SELECTORS.CONTACTS_SECTION_CONTAINER);\n };\n\n /**\n * Get the container element for the requests section.\n *\n * @param {Object} body Contacts page body element.\n * @return {Object}\n */\n var getRequestsSectionContainer = function(body) {\n return body.find(SELECTORS.REQUESTS_SECTION_CONTAINER);\n };\n\n /**\n * Get the element that triggers showing the contacts section.\n *\n * @param {Object} body Contacts page body element.\n * @return {Object}\n */\n var getShowContactsAction = function(body) {\n return body.find(SELECTORS.ACTION_SHOW_CONTACTS_SECTION);\n };\n\n /**\n * Get the element that triggers showing the requests section.\n *\n * @param {Object} body Contacts page body element.\n * @return {Object}\n */\n var getShowRequestsAction = function(body) {\n return body.find(SELECTORS.ACTION_SHOW_REQUESTS_SECTION);\n };\n\n /**\n * Check if the given section is visible.\n *\n * @param {Object} sectionRoot The root element for the section\n * @return {Bool}\n */\n var isSectionVisible = function(sectionRoot) {\n return sectionRoot.hasClass('active');\n };\n\n /**\n * Decrement the contact request count. If the count is zero or below then\n * hide the count.\n *\n * @param {Object} body Conversation body container element.\n * @return {Function} A function to handle decrementing the count.\n */\n var decrementContactRequestCount = function(body) {\n return function() {\n var countContainer = body.find(SELECTORS.CONTACT_REQUEST_COUNT);\n var count = parseInt(countContainer.text(), 10);\n count = isNaN(count) ? 0 : count - 1;\n\n if (count <= 0) {\n countContainer.addClass('hidden');\n } else {\n countContainer.text(count);\n }\n };\n };\n\n /**\n * Listen to and handle events for contacts.\n *\n * @param {Object} body Contacts body container element.\n */\n var registerEventListeners = function(body) {\n var contactsSection = getContactsSectionContainer(body);\n var requestsSection = getRequestsSectionContainer(body);\n var showContactsAction = getShowContactsAction(body);\n var showRequestsAction = getShowRequestsAction(body);\n\n showContactsAction.on('show.bs.tab', function() {\n ContactsSection.show(contactsSection);\n });\n\n showRequestsAction.on('show.bs.tab', function() {\n RequestsSection.show(requestsSection);\n });\n\n PubSub.subscribe(MessageDrawerEvents.CONTACT_REQUEST_ACCEPTED, decrementContactRequestCount(body));\n PubSub.subscribe(MessageDrawerEvents.CONTACT_REQUEST_DECLINED, decrementContactRequestCount(body));\n };\n\n /**\n * Setup the contact page.\n *\n * @param {string} namespace The route namespace.\n * @param {Object} header Contacts header container element.\n * @param {Object} body Contacts body container element.\n * @param {Object} footer Contacts footer container element.\n * @param {String|null} tab Tab to show, either 'requests' or 'contacts', if any.\n * @return {Object} jQuery promise\n */\n var show = function(namespace, header, body, footer, tab) {\n body = $(body);\n\n if (!body.attr('data-contacts-init')) {\n registerEventListeners(body);\n body.attr('data-contacts-init', true);\n }\n\n var contactsSection = getContactsSectionContainer(body);\n var requestsSection = getRequestsSectionContainer(body);\n\n if (tab) {\n var showContactsAction = getShowContactsAction(body);\n var showRequestsAction = getShowRequestsAction(body);\n\n // Unfortunately we need to hardcode the class changes here rather than trigger\n // the bootstrap tab functionality because the bootstrap JS doesn't appear to be\n // loaded by this point which means the tab plugin isn't added and the event listeners\n // haven't been set up so we can't just trigger a click either.\n if (tab == 'requests') {\n showContactsAction.removeClass('active');\n contactsSection.removeClass('show active');\n showRequestsAction.addClass('active');\n requestsSection.addClass('show active');\n } else {\n showRequestsAction.removeClass('active');\n requestsSection.removeClass('show active');\n showContactsAction.addClass('active');\n contactsSection.addClass('show active');\n }\n }\n\n if (isSectionVisible(contactsSection)) {\n ContactsSection.show(contactsSection);\n } else {\n RequestsSection.show(requestsSection);\n }\n\n return $.Deferred().resolve().promise();\n };\n\n /**\n * String describing this page used for aria-labels.\n *\n * @return {Object} jQuery promise\n */\n var description = function() {\n return Str.get_string('messagedrawerviewcontacts', 'core_message');\n };\n\n return {\n show: show,\n description: description\n };\n});\n"],"file":"message_drawer_view_contacts.min.js"}
\ No newline at end of file
diff --git a/message/amd/src/message_drawer.js b/message/amd/src/message_drawer.js
index d7a1bada047..a40ae892da1 100644
--- a/message/amd/src/message_drawer.js
+++ b/message/amd/src/message_drawer.js
@@ -270,22 +270,18 @@ function(
* @param {int} sendToUser Should we message someone now?
* @param {int} conversationId The value of the conversation id, null if none
*/
- var init = function(root, uniqueId, alwaysVisible, sendToUser, conversationId) {
+ var init = function(root, uniqueId, alwaysVisible, route) {
root = $(root);
createRoutes(uniqueId, root);
registerEventListeners(uniqueId, root, alwaysVisible);
+
if (alwaysVisible) {
show(uniqueId, root);
- // Are we sending to a specific user?
- if (sendToUser) {
- // Check if a conversation already exists, if not, create one.
- if (conversationId) {
- Router.go(uniqueId, Routes.VIEW_CONVERSATION, conversationId);
- } else {
- Router.go(uniqueId, Routes.VIEW_CONVERSATION, null, 'create', sendToUser);
- }
- } else if (conversationId) { // We aren't sending to a specific user, but to a group conversation.
- Router.go(uniqueId, Routes.VIEW_CONVERSATION, conversationId);
+
+ if (route) {
+ var routeParams = route.params || [];
+ routeParams = [uniqueId, route.path].concat(routeParams);
+ Router.go.apply(null, routeParams);
}
}
};
diff --git a/message/amd/src/message_drawer_view_contacts.js b/message/amd/src/message_drawer_view_contacts.js
index f64898a6ae5..ab255c78a17 100644
--- a/message/amd/src/message_drawer_view_contacts.js
+++ b/message/amd/src/message_drawer_view_contacts.js
@@ -66,6 +66,26 @@ function(
return body.find(SELECTORS.REQUESTS_SECTION_CONTAINER);
};
+ /**
+ * Get the element that triggers showing the contacts section.
+ *
+ * @param {Object} body Contacts page body element.
+ * @return {Object}
+ */
+ var getShowContactsAction = function(body) {
+ return body.find(SELECTORS.ACTION_SHOW_CONTACTS_SECTION);
+ };
+
+ /**
+ * Get the element that triggers showing the requests section.
+ *
+ * @param {Object} body Contacts page body element.
+ * @return {Object}
+ */
+ var getShowRequestsAction = function(body) {
+ return body.find(SELECTORS.ACTION_SHOW_REQUESTS_SECTION);
+ };
+
/**
* Check if the given section is visible.
*
@@ -105,8 +125,8 @@ function(
var registerEventListeners = function(body) {
var contactsSection = getContactsSectionContainer(body);
var requestsSection = getRequestsSectionContainer(body);
- var showContactsAction = body.find(SELECTORS.ACTION_SHOW_CONTACTS_SECTION);
- var showRequestsAction = body.find(SELECTORS.ACTION_SHOW_REQUESTS_SECTION);
+ var showContactsAction = getShowContactsAction(body);
+ var showRequestsAction = getShowRequestsAction(body);
showContactsAction.on('show.bs.tab', function() {
ContactsSection.show(contactsSection);
@@ -126,9 +146,11 @@ function(
* @param {string} namespace The route namespace.
* @param {Object} header Contacts header container element.
* @param {Object} body Contacts body container element.
+ * @param {Object} footer Contacts footer container element.
+ * @param {String|null} tab Tab to show, either 'requests' or 'contacts', if any.
* @return {Object} jQuery promise
*/
- var show = function(namespace, header, body) {
+ var show = function(namespace, header, body, footer, tab) {
body = $(body);
if (!body.attr('data-contacts-init')) {
@@ -139,6 +161,27 @@ function(
var contactsSection = getContactsSectionContainer(body);
var requestsSection = getRequestsSectionContainer(body);
+ if (tab) {
+ var showContactsAction = getShowContactsAction(body);
+ var showRequestsAction = getShowRequestsAction(body);
+
+ // Unfortunately we need to hardcode the class changes here rather than trigger
+ // the bootstrap tab functionality because the bootstrap JS doesn't appear to be
+ // loaded by this point which means the tab plugin isn't added and the event listeners
+ // haven't been set up so we can't just trigger a click either.
+ if (tab == 'requests') {
+ showContactsAction.removeClass('active');
+ contactsSection.removeClass('show active');
+ showRequestsAction.addClass('active');
+ requestsSection.addClass('show active');
+ } else {
+ showRequestsAction.removeClass('active');
+ requestsSection.removeClass('show active');
+ showContactsAction.addClass('active');
+ contactsSection.addClass('show active');
+ }
+ }
+
if (isSectionVisible(contactsSection)) {
ContactsSection.show(contactsSection);
} else {
diff --git a/message/classes/helper.php b/message/classes/helper.php
index 5136ce81f2c..f2ad3c60371 100644
--- a/message/classes/helper.php
+++ b/message/classes/helper.php
@@ -687,9 +687,15 @@ class helper {
* @param bool $isdrawer Are we are rendering the drawer or is this on a full page?
* @param int|null $sendtouser The ID of the user we want to send a message to
* @param int|null $conversationid The ID of the conversation we want to load
+ * @param string|null $view The first view to load in the message widget
* @return string The HTML.
*/
- public static function render_messaging_widget(bool $isdrawer, int $sendtouser = null, int $conversationid = null) {
+ public static function render_messaging_widget(
+ bool $isdrawer,
+ int $sendtouser = null,
+ int $conversationid = null,
+ string $view = null
+ ) {
global $USER, $CFG, $PAGE;
// Early bail out conditions.
@@ -765,18 +771,24 @@ class helper {
'messageurl' => $messageurl,
'notification' => $notification
],
- 'sendtouser' => false,
- 'conversationid' => false,
'isdrawer' => $isdrawer
];
- if ($sendtouser) {
- $templatecontext['sendtouser'] = $sendtouser;
+ if ($sendtouser || $conversationid) {
+ $route = [
+ 'path' => 'view-conversation',
+ 'params' => $conversationid ? [$conversationid] : [null, 'create', $sendtouser]
+ ];
+ } else if ($view === 'contactrequests') {
+ $route = [
+ 'path' => 'view-contacts',
+ 'params' => ['requests']
+ ];
+ } else {
+ $route = null;
}
- if ($conversationid) {
- $templatecontext['conversationid'] = $conversationid;
- }
+ $templatecontext['route'] = json_encode($route);
return $renderer->render_from_template($template, $templatecontext);
}
diff --git a/message/index.php b/message/index.php
index ebc1f2776cb..1fcac5ab2b7 100644
--- a/message/index.php
+++ b/message/index.php
@@ -36,6 +36,7 @@ if (empty($CFG->messaging)) {
// The id of the user we want to view messages from.
$id = optional_param('id', 0, PARAM_INT);
+$view = optional_param('view', null, PARAM_ALPHANUM);
// It's possible a user may come from a link where these parameters are specified.
// We no longer support viewing another user's messaging area (that can be achieved
// via the 'Log-in as' feature). The 'user2' value takes preference over 'id'.
@@ -90,5 +91,5 @@ if (!get_user_preferences('core_message_migrate_data', false)) {
\core\output\notification::NOTIFY_WARNING);
echo $OUTPUT->render($notify);
}
-echo \core_message\helper::render_messaging_widget(false, $userid, $conversationid);
+echo \core_message\helper::render_messaging_widget(false, $userid, $conversationid, $view);
echo $OUTPUT->footer();
diff --git a/message/pendingcontactrequests.php b/message/pendingcontactrequests.php
new file mode 100644
index 00000000000..df52d920d44
--- /dev/null
+++ b/message/pendingcontactrequests.php
@@ -0,0 +1,33 @@
+.
+
+/**
+ * This is a placeholder file for a legacy implementation.
+ *
+ * @package core
+ * @copyright 2019 Ryan Wyllie
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+// Disable moodle specific debug messages since we're just redirecting.
+define('NO_DEBUG_DISPLAY', true);
+require('../config.php');
+
+require_login(null, false);
+
+// We have a bunch of old notifications (both internal and external, e.g. email) that
+// reference this URL which means we can't remove it so let's just redirect.
+redirect("{$CFG->wwwroot}/message/index.php?view=contactrequests");
diff --git a/message/templates/message_index.mustache b/message/templates/message_index.mustache
index 52fc66cae10..65c44fc6288 100644
--- a/message/templates/message_index.mustache
+++ b/message/templates/message_index.mustache
@@ -79,6 +79,6 @@
{{#js}}
require(['jquery', 'core_message/message_drawer'], function($, MessageDrawer) {
var root = $('#message-index-{{uniqid}}');
- MessageDrawer.init(root, '{{uniqid}}', true, {{sendtouser}}, {{conversationid}});
+ MessageDrawer.init(root, '{{uniqid}}', true, {{{route}}});
});
{{/js}}
\ No newline at end of file
diff --git a/version.php b/version.php
index d3b5604a427..105d8d4b469 100644
--- a/version.php
+++ b/version.php
@@ -29,7 +29,7 @@
defined('MOODLE_INTERNAL') || die();
-$version = 2019072500.00; // YYYYMMDD = weekly release date of this DEV branch.
+$version = 2019072500.01; // YYYYMMDD = weekly release date of this DEV branch.
// RR = release increments - 00 in DEV branches.
// .XX = incremental changes.