mirror of
https://github.com/moodle/moodle.git
synced 2025-01-18 22:08:20 +01:00
MDL-63915 core_message: removed unused AMD modules
This commit is contained in:
parent
b01d0535bc
commit
273dadeb50
1
message/amd/build/message_area.min.js
vendored
1
message/amd/build/message_area.min.js
vendored
@ -1 +0,0 @@
|
||||
define(["jquery","core_message/message_area_contacts","core_message/message_area_messages","core_message/message_area_profile","core_message/message_area_tabs","core_message/message_area_search"],function(a,b,c,d,e,f){function g(b,c,d,e){this.node=a(b),this.pollmin=c,this.pollmax=d,this.polltimeout=e,this._init()}return g.prototype.node=null,g.prototype.pollmin=null,g.prototype.pollmax=null,g.prototype.polltimeout=null,g.prototype._init=function(){new b(this),new c(this),new d(this),new e(this),new f(this)},g.prototype.onDelegateEvent=function(a,b,c){this.node.on(a,b,c)},g.prototype.onCustomEvent=function(a,b){this.node.on(a,b)},g.prototype.trigger=function(a,b){"undefined"==typeof b&&(b=""),this.node.trigger(a,b)},g.prototype.find=function(a){return this.node.find(a)},g.prototype.getCurrentUserId=function(){return this.node.data("userid")},g.prototype.showContactsFirst=function(){return!!this.node.data("displaycontacts")},g});
|
@ -1 +0,0 @@
|
||||
define(["core_message/message_area_events"],function(a){function b(a){this.messageArea=a}var c={MESSAGES:"[data-region='messages']"};return b.prototype.messageArea=null,b.prototype.chooseMessagesToDelete=function(){0!==this.messageArea.find(c.MESSAGES).length&&this.messageArea.trigger(a.CHOOSEMESSAGESTODELETE)},b});
|
File diff suppressed because one or more lines are too long
1
message/amd/build/message_area_events.min.js
vendored
1
message/amd/build/message_area_events.min.js
vendored
@ -1 +0,0 @@
|
||||
define([],function(){return{CANCELDELETEMESSAGES:"cancel-delete-messages",CHOOSEMESSAGESTODELETE:"choose-messages-to-delete",CONTACTADDED:"contact-added",CONTACTBLOCKED:"contact-blocked",CONTACTREMOVED:"contact-removed",CONTACTSELECTED:"contact-selected",CONTACTSSELECTED:"contacts-selected",CONTACTUNBLOCKED:"contact-unblocked",CONVERSATIONDELETED:"conversation-deleted",CONVERSATIONSELECTED:"conversation-selected",CONVERSATIONSSELECTED:"conversations-selected",MESSAGESDELETED:"messages-deleted",MESSAGESEARCHCANCELED:"message-search-canceled",MESSAGESENT:"message-sent",SENDMESSAGE:"message-send",USERSSEARCHCANCELED:"users-search-canceled"}});
|
File diff suppressed because one or more lines are too long
@ -1 +0,0 @@
|
||||
define(["jquery","core/ajax","core/templates","core/notification","core/str","core/config","core/custom_interaction_events","core_message/message_area_events"],function(a,b,c,d,e,f,g,h){function i(a){this.messageArea=a,this._init()}var j={PROFILE:"[data-region='profile']",PROFILEADDCONTACT:"[data-action='profile-add-contact']",PROFILEBLOCKCONTACT:"[data-action='profile-block-contact']",PROFILEREMOVECONTACT:"[data-action='profile-remove-contact']",PROFILESENDMESSAGE:"[data-action='profile-send-message']",PROFILEUNBLOCKCONTACT:"[data-action='profile-unblock-contact']",PROFILEVIEW:"[data-action='profile-view']",SHOWCONTACTS:"[data-action='show-contacts']",MESSAGESAREA:"[data-region='messages-area']",MESSAGINGAREA:"[data-region='messaging-area']"};return i.prototype.messageArea=null,i.prototype._init=function(){g.define(this.messageArea.node,[g.events.activate]),this.messageArea.onCustomEvent(h.CONTACTSELECTED,this._viewProfile.bind(this)),this.messageArea.onDelegateEvent(g.events.activate,j.PROFILEVIEW,function(a,b){this._viewFullProfile(),b.originalEvent.preventDefault()}.bind(this)),this.messageArea.onDelegateEvent(g.events.activate,j.PROFILESENDMESSAGE,function(a,b){this._sendMessage(),b.originalEvent.preventDefault()}.bind(this)),this.messageArea.onDelegateEvent(g.events.activate,j.PROFILEUNBLOCKCONTACT,function(a,b){this._unblockContact(),b.originalEvent.preventDefault()}.bind(this)),this.messageArea.onDelegateEvent(g.events.activate,j.PROFILEBLOCKCONTACT,function(a,b){this._blockContact(),b.originalEvent.preventDefault()}.bind(this)),this.messageArea.onDelegateEvent(g.events.activate,j.PROFILEADDCONTACT,function(a,b){this._addContact(),b.originalEvent.preventDefault()}.bind(this)),this.messageArea.onDelegateEvent(g.events.activate,j.PROFILEREMOVECONTACT,function(a,b){this._removeContact(),b.originalEvent.preventDefault()}.bind(this)),this.messageArea.onDelegateEvent(g.events.activate,j.SHOWCONTACTS,this._hideMessagingArea.bind(this))},i.prototype._viewProfile=function(a,e){c.render("core/loading",{}).done(function(a,b){c.replaceNodeContents(this.messageArea.find(j.MESSAGESAREA),a,b)}.bind(this));var f=b.call([{methodname:"core_message_data_for_messagearea_get_profile",args:{currentuserid:this.messageArea.getCurrentUserId(),otheruserid:e}}]);return f[0].then(function(a){return c.render("core_message/message_area_profile",a)}).then(function(a,b){c.replaceNodeContents(this.messageArea.find(j.MESSAGESAREA),a,b)}.bind(this)).fail(d.exception)},i.prototype._viewFullProfile=function(){window.location.href=f.wwwroot+"/user/profile.php?id="+this._getUserId()},i.prototype._sendMessage=function(){this.messageArea.trigger(h.SENDMESSAGE,this._getUserId())},i.prototype._blockContact=function(){var a=this._performAction("core_message_block_user","unblockcontact","profile-block-contact","profile-unblock-contact","");return a.then(function(){this.messageArea.trigger(h.CONTACTBLOCKED,this._getUserId())}.bind(this))},i.prototype._unblockContact=function(){var a=this._performAction("core_message_unblock_user","blockcontact","profile-unblock-contact","profile-block-contact","danger");return a.then(function(){this.messageArea.trigger(h.CONTACTUNBLOCKED,this._getUserId())}.bind(this))},i.prototype._addContact=function(){var a=this._performAction("core_message_create_contact_request","removecontact","profile-add-contact","profile-remove-contact","danger");return a.then(function(){this.messageArea.trigger(h.CONTACTADDED,this._getUserId())}.bind(this))},i.prototype._removeContact=function(){var a=this._performAction("core_message_delete_contacts","addcontact","profile-remove-contact","profile-add-contact","");return a.then(function(){this.messageArea.trigger(h.CONTACTREMOVED,this._getUserId())}.bind(this))},i.prototype._performAction=function(a,c,f,g,h){var i="";switch(a){case"core_message_block_user":i={userid:this.messageArea.getCurrentUserId(),blockeduserid:this._getUserId()};break;case"core_message_unblock_user":i={userid:this.messageArea.getCurrentUserId(),unblockeduserid:this._getUserId()};break;case"core_message_create_contact_request":i={userid:this.messageArea.getCurrentUserId(),requesteduserid:this._getUserId()};break;default:i={userid:this.messageArea.getCurrentUserId(),userids:[this._getUserId()]}}var j=b.call([{methodname:a,args:i}]);return j[0].then(function(){return e.get_string(c,"message")}).then(function(a){this._changeText(a,f,g,h)}.bind(this)).fail(d.exception)},i.prototype._changeText=function(a,b,c,d){var e=this.messageArea.find("[data-action='"+b+"']");e.text(a),e.removeClass(),d&&e.addClass(d),e.attr("data-action",c)},i.prototype._getUserId=function(){return this.messageArea.find(j.PROFILE).data("userid")},i.prototype._hideMessagingArea=function(){this.messageArea.find(j.MESSAGINGAREA).removeClass("show-messages").addClass("hide-messages")},i});
|
1
message/amd/build/message_area_search.min.js
vendored
1
message/amd/build/message_area_search.min.js
vendored
File diff suppressed because one or more lines are too long
1
message/amd/build/message_area_tabs.min.js
vendored
1
message/amd/build/message_area_tabs.min.js
vendored
@ -1 +0,0 @@
|
||||
define(["core/custom_interaction_events","core_message/message_area_events"],function(a,b){function c(a){this.messageArea=a,this._init()}var d={ACTIVECONTACTSTAB:"[data-region='contacts-area'] [role='tab'][aria-selected='true']",CONTACTSPANELS:"[data-region='contacts']",VIEWCONTACTS:"[data-action='contacts-view']",VIEWCONVERSATIONS:"[data-action='conversations-view']"};return c.prototype.messageArea=null,c.prototype._init=function(){a.define(this.messageArea.node,[a.events.activate,a.events.up,a.events.down,a.events.next,a.events.previous,a.events.ctrlPageUp,a.events.ctrlPageDown]),this.messageArea.onDelegateEvent(a.events.activate,d.VIEWCONVERSATIONS,this._viewConversations.bind(this)),this.messageArea.onDelegateEvent(a.events.activate,d.VIEWCONTACTS,this._viewContacts.bind(this)),this.messageArea.onDelegateEvent(a.events.up,d.VIEWCONVERSATIONS,this._toggleTabs.bind(this)),this.messageArea.onDelegateEvent(a.events.down,d.VIEWCONVERSATIONS,this._toggleTabs.bind(this)),this.messageArea.onDelegateEvent(a.events.next,d.VIEWCONVERSATIONS,this._toggleTabs.bind(this)),this.messageArea.onDelegateEvent(a.events.previous,d.VIEWCONVERSATIONS,this._toggleTabs.bind(this)),this.messageArea.onDelegateEvent(a.events.up,d.VIEWCONTACTS,this._toggleTabs.bind(this)),this.messageArea.onDelegateEvent(a.events.down,d.VIEWCONTACTS,this._toggleTabs.bind(this)),this.messageArea.onDelegateEvent(a.events.next,d.VIEWCONTACTS,this._toggleTabs.bind(this)),this.messageArea.onDelegateEvent(a.events.previous,d.VIEWCONTACTS,this._toggleTabs.bind(this)),this.messageArea.onDelegateEvent(a.events.ctrlPageUp,d.CONTACTSPANELS,this._toggleTabs.bind(this)),this.messageArea.onDelegateEvent(a.events.ctrlPageDown,d.CONTACTSPANELS,this._toggleTabs.bind(this)),this.messageArea.onCustomEvent(b.MESSAGESENT,function(){this._selectTab(d.VIEWCONVERSATIONS,d.VIEWCONTACTS)}.bind(this))},c.prototype._viewConversations=function(){this.messageArea.trigger(b.CONVERSATIONSSELECTED),this._selectTab(d.VIEWCONVERSATIONS,d.VIEWCONTACTS)},c.prototype._viewContacts=function(){this.messageArea.trigger(b.CONTACTSSELECTED),this._selectTab(d.VIEWCONTACTS,d.VIEWCONVERSATIONS)},c.prototype._selectTab=function(a,b){b=this.messageArea.find(b),b.removeClass("selected"),b.attr("aria-selected","false"),b.attr("tabindex","-1"),a=this.messageArea.find(a),a.addClass("selected"),a.attr("aria-selected","true"),a.attr("tabindex","0")},c.prototype._toggleTabs=function(a,b){var c=this.messageArea.find(d.ACTIVECONTACTSTAB);c.is(d.VIEWCONVERSATIONS)?this._viewContacts():this._viewConversations(),this.messageArea.find(d.ACTIVECONTACTSTAB).focus(),a.preventDefault(),a.stopPropagation(),b.originalEvent.preventDefault(),b.originalEvent.stopPropagation()},c});
|
1
message/amd/build/message_preferences.min.js
vendored
1
message/amd/build/message_preferences.min.js
vendored
@ -1 +0,0 @@
|
||||
define(["jquery","core/ajax","core/notification","core_message/message_notification_preference","core/custom_interaction_events"],function(a,b,c,d,e){var f={PREFERENCE:"[data-state]",PREFERENCES_CONTAINER:'[data-region="preferences-container"]',CONTACTABLE_PRIVACY_CONTAINER:'[data-region="privacy-setting-container"]'},g=function(b){this.root=a(b),this.userId=this.root.find(f.PREFERENCES_CONTAINER).attr("data-user-id"),this.registerEventListeners()};return g.prototype.preferencesDisabled=function(){return this.root.find(f.PREFERENCES_CONTAINER).hasClass("disabled")},g.prototype.saveContactablePrivacySetting=function(){var d=this.root.find(f.CONTACTABLE_PRIVACY_CONTAINER),e=a("input[type='radio']:checked").val();if(d.hasClass("loading"))return a.Deferred().resolve();d.addClass("loading");var g={methodname:"core_user_update_user_preferences",args:{userid:this.userId,preferences:[{type:d.attr("data-preference-key"),value:e}]}};return b.call([g])[0].fail(c.exception).always(function(){d.removeClass("loading")})},g.prototype.registerEventListeners=function(){e.define(this.root,[e.events.activate]),this.root.on("change",function(b){if("message_blocknoncontacts"==b.target.name)this.saveContactablePrivacySetting();else if(!this.preferencesDisabled()){var c=a(b.target).closest(f.PREFERENCES_CONTAINER),e=a(b.target).closest(f.PREFERENCE),g=new d(c,this.userId);e.addClass("loading"),g.save().always(function(){e.removeClass("loading")})}}.bind(this))},g});
|
@ -1,131 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* This module instantiates the functionality of the messaging area.
|
||||
*
|
||||
* @module core_message/message_area
|
||||
* @package core_message
|
||||
* @copyright 2016 Mark Nelson <markn@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['jquery', 'core_message/message_area_contacts', 'core_message/message_area_messages',
|
||||
'core_message/message_area_profile', 'core_message/message_area_tabs', 'core_message/message_area_search'],
|
||||
function($, Contacts, Messages, Profile, Tabs, Search) {
|
||||
|
||||
/**
|
||||
* Messagearea class.
|
||||
*
|
||||
* @param {String} selector The selector for the page region containing the message area.
|
||||
* @param {int} pollmin
|
||||
* @param {int} pollmax
|
||||
* @param {int} polltimeout
|
||||
*/
|
||||
function Messagearea(selector, pollmin, pollmax, polltimeout) {
|
||||
this.node = $(selector);
|
||||
this.pollmin = pollmin;
|
||||
this.pollmax = pollmax;
|
||||
this.polltimeout = polltimeout;
|
||||
this._init();
|
||||
}
|
||||
|
||||
/** @type {jQuery} The jQuery node for the page region containing the message area. */
|
||||
Messagearea.prototype.node = null;
|
||||
|
||||
/** @type {int} The minimum time to poll for messages. */
|
||||
Messagearea.prototype.pollmin = null;
|
||||
|
||||
/** @type {int} The maximum time to poll for messages. */
|
||||
Messagearea.prototype.pollmax = null;
|
||||
|
||||
/** @type {int} The time used once we have reached the maximum polling time. */
|
||||
Messagearea.prototype.polltimeout = null;
|
||||
|
||||
/**
|
||||
* Initialise the other objects we require.
|
||||
*/
|
||||
Messagearea.prototype._init = function() {
|
||||
new Contacts(this);
|
||||
new Messages(this);
|
||||
new Profile(this);
|
||||
new Tabs(this);
|
||||
new Search(this);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles adding a delegate event to the messaging area node.
|
||||
*
|
||||
* @param {String} action The action we are listening for
|
||||
* @param {String} selector The selector for the page we are assigning the action to
|
||||
* @param {Function} callable The function to call when the event happens
|
||||
*/
|
||||
Messagearea.prototype.onDelegateEvent = function(action, selector, callable) {
|
||||
this.node.on(action, selector, callable);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles adding a custom event to the messaging area node.
|
||||
*
|
||||
* @param {String} action The action we are listening for
|
||||
* @param {Function} callable The function to call when the event happens
|
||||
*/
|
||||
Messagearea.prototype.onCustomEvent = function(action, callable) {
|
||||
this.node.on(action, callable);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles triggering an event on the messaging area node.
|
||||
*
|
||||
* @param {String} event The selector for the page region containing the message area
|
||||
* @param {Object=} data The data to pass when we trigger the event
|
||||
*/
|
||||
Messagearea.prototype.trigger = function(event, data) {
|
||||
if (typeof data == 'undefined') {
|
||||
data = '';
|
||||
}
|
||||
this.node.trigger(event, data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles finding a node in the messaging area.
|
||||
*
|
||||
* @param {String} selector The selector for the node we are looking for
|
||||
* @return {jQuery} The node
|
||||
*/
|
||||
Messagearea.prototype.find = function(selector) {
|
||||
return this.node.find(selector);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the ID of the user whose message area we are viewing.
|
||||
*
|
||||
* @return {int} The user id
|
||||
*/
|
||||
Messagearea.prototype.getCurrentUserId = function() {
|
||||
return this.node.data('userid');
|
||||
};
|
||||
|
||||
/**
|
||||
* Function to determine if we should be showing contacts initially or messages.
|
||||
*
|
||||
* @return {boolean} True to show contacts first, otherwise show messages.
|
||||
*/
|
||||
Messagearea.prototype.showContactsFirst = function() {
|
||||
return !!this.node.data('displaycontacts');
|
||||
};
|
||||
|
||||
return Messagearea;
|
||||
}
|
||||
);
|
@ -1,54 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* The module handles any actions we perform on the message area.
|
||||
*
|
||||
* @module core_message/message_area_actions
|
||||
* @package core_message
|
||||
* @copyright 2016 Mark Nelson <markn@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['core_message/message_area_events'], function(Events) {
|
||||
|
||||
/** @type {Object} The list of selectors for the message area. */
|
||||
var SELECTORS = {
|
||||
MESSAGES: "[data-region='messages']"
|
||||
};
|
||||
|
||||
/**
|
||||
* Actions class.
|
||||
*
|
||||
* @param {Messagearea} messageArea The messaging area object.
|
||||
*/
|
||||
function Actions(messageArea) {
|
||||
this.messageArea = messageArea;
|
||||
}
|
||||
|
||||
/** @type {Messagearea} The messaging area object. */
|
||||
Actions.prototype.messageArea = null;
|
||||
|
||||
/**
|
||||
* Handles when we have selected to delete messages.
|
||||
*/
|
||||
Actions.prototype.chooseMessagesToDelete = function() {
|
||||
// Only fire the event if we are viewing messages.
|
||||
if (this.messageArea.find(SELECTORS.MESSAGES).length !== 0) {
|
||||
this.messageArea.trigger(Events.CHOOSEMESSAGESTODELETE);
|
||||
}
|
||||
};
|
||||
|
||||
return Actions;
|
||||
});
|
@ -1,711 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* This module handles the contacts area of the messaging area.
|
||||
*
|
||||
* @module core_message/message_area_contacts
|
||||
* @package core_message
|
||||
* @copyright 2016 Mark Nelson <markn@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/custom_interaction_events', 'core/str',
|
||||
'core_message/message_area_events'],
|
||||
function($, Ajax, Templates, Notification, CustomEvents, Str, Events) {
|
||||
|
||||
/** @type {Object} The list of selectors for the message area. */
|
||||
var SELECTORS = {
|
||||
CONTACT: "[data-region='contact']",
|
||||
CONTACTICONBLOCKED: "[data-region='contact-icon-blocked']",
|
||||
CONTACTS: "[data-region='contacts'][data-region-content='contacts']",
|
||||
CONTACTSAREA: "[data-region='contacts-area']",
|
||||
CONVERSATIONS: "[data-region='contacts'][data-region-content='conversations']",
|
||||
COURSE: "[data-region='course']",
|
||||
LASTMESSAGETEXT: "[data-region='last-message-text']",
|
||||
LASTMESSAGEUSER: "[data-region='last-message-user']",
|
||||
LOADINGICON: '.loading-icon',
|
||||
MESSAGETEXT: "[data-region='message-text']",
|
||||
MESSAGINGAREA: "[data-region='messaging-area']",
|
||||
NOCONTACTS: "[data-region=no-contacts]",
|
||||
SEARCHBOX: "[data-region='search-box']",
|
||||
SEARCHRESULTSAREA: "[data-region='search-results-area']",
|
||||
SEARCHTEXTAREA: "[data-region='search-text-area']",
|
||||
SELECTEDVIEWCONVERSATION: "[data-action='view-contact-msg'].selected",
|
||||
SELECTEDVIEWPROFILE: "[data-action='view-contact-profile'].selected",
|
||||
SHOWMESSAGES: "[data-action='show-messages']",
|
||||
VIEWCONVERSATION: "[data-action='view-contact-msg']",
|
||||
VIEWPROFILE: "[data-action='view-contact-profile']"
|
||||
};
|
||||
|
||||
/**
|
||||
* Contacts class.
|
||||
*
|
||||
* @param {Messagearea} messageArea The messaging area object.
|
||||
*/
|
||||
function Contacts(messageArea) {
|
||||
this.messageArea = messageArea;
|
||||
this._init();
|
||||
}
|
||||
|
||||
/** @type {Boolean} checks if we are currently loading conversations */
|
||||
Contacts.prototype._isLoadingConversations = false;
|
||||
|
||||
/** @type {Boolean} checks if we are currently loading contacts */
|
||||
Contacts.prototype._isLoadingContacts = false;
|
||||
|
||||
/** @type {int} the number of contacts displayed */
|
||||
Contacts.prototype._numContactsDisplayed = 0;
|
||||
|
||||
/** @type {int} the number of contacts to retrieve */
|
||||
Contacts.prototype._numContactsToRetrieve = 20;
|
||||
|
||||
/** @type {int} the number of conversations displayed */
|
||||
Contacts.prototype._numConversationsDisplayed = 0;
|
||||
|
||||
/** @type {int} the number of conversations to retrieve */
|
||||
Contacts.prototype._numConversationsToRetrieve = 20;
|
||||
|
||||
/** @type {int} the number of chars of the message to show */
|
||||
Contacts.prototype._messageLength = 60;
|
||||
|
||||
/** @type {Messagearea} The messaging area object. */
|
||||
Contacts.prototype.messageArea = null;
|
||||
|
||||
/**
|
||||
* Initialise the event listeners.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Contacts.prototype._init = function() {
|
||||
CustomEvents.define(this.messageArea.node, [
|
||||
CustomEvents.events.activate,
|
||||
CustomEvents.events.down,
|
||||
CustomEvents.events.up,
|
||||
]);
|
||||
|
||||
this.messageArea.onCustomEvent(Events.MESSAGESEARCHCANCELED, this._viewConversations.bind(this));
|
||||
this.messageArea.onCustomEvent(Events.USERSSEARCHCANCELED, this._viewContacts.bind(this));
|
||||
this.messageArea.onCustomEvent(Events.CONTACTSSELECTED, this._viewContacts.bind(this));
|
||||
this.messageArea.onCustomEvent(Events.CONVERSATIONDELETED, this._deleteConversation.bind(this));
|
||||
this.messageArea.onCustomEvent(Events.CONVERSATIONSSELECTED, this._viewConversations.bind(this));
|
||||
this.messageArea.onCustomEvent(Events.CONTACTSSELECTED, this._viewContacts.bind(this));
|
||||
this.messageArea.onCustomEvent(Events.MESSAGESDELETED, this._updateLastMessage.bind(this));
|
||||
this.messageArea.onCustomEvent(Events.MESSAGESENT, this._handleMessageSent.bind(this));
|
||||
this.messageArea.onCustomEvent(Events.CONTACTREMOVED, function(e, userid) {
|
||||
this._removeContact(SELECTORS.CONTACTS, userid);
|
||||
}.bind(this));
|
||||
this.messageArea.onCustomEvent(Events.CONTACTADDED, function(e, userid) {
|
||||
this._addContact(userid);
|
||||
}.bind(this));
|
||||
this.messageArea.onCustomEvent(Events.CONTACTBLOCKED, function(e, userid) {
|
||||
this._blockContact(userid);
|
||||
}.bind(this));
|
||||
this.messageArea.onCustomEvent(Events.CONTACTUNBLOCKED, function(e, userid) {
|
||||
this._unblockContact(userid);
|
||||
}.bind(this));
|
||||
this.messageArea.onCustomEvent(Events.CHOOSEMESSAGESTODELETE,
|
||||
this._startDeleting.bind(this));
|
||||
this.messageArea.onCustomEvent(Events.CANCELDELETEMESSAGES,
|
||||
this._stopDeleting.bind(this));
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.activate, SELECTORS.VIEWCONVERSATION,
|
||||
this._viewConversation.bind(this));
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.activate, SELECTORS.VIEWPROFILE,
|
||||
this._viewContact.bind(this));
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.activate, SELECTORS.SHOWMESSAGES,
|
||||
this._showMessagingArea.bind(this));
|
||||
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.up, SELECTORS.CONTACT,
|
||||
this._selectPreviousContact.bind(this));
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.down, SELECTORS.CONTACT,
|
||||
this._selectNextContact.bind(this));
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.up, SELECTORS.VIEWCONVERSATION,
|
||||
this._selectPreviousConversation.bind(this));
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.down, SELECTORS.VIEWCONVERSATION,
|
||||
this._selectNextConversation.bind(this));
|
||||
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.up, SELECTORS.COURSE, this._selectPreviousCourse.bind());
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.down, SELECTORS.COURSE, this._selectNextCourse.bind());
|
||||
|
||||
this.messageArea.onDelegateEvent('focus', SELECTORS.SEARCHBOX, this._setSearching.bind(this));
|
||||
this.messageArea.onDelegateEvent('blur', SELECTORS.SEARCHBOX, this._clearSearching.bind(this));
|
||||
|
||||
// Now enable the ability to infinitely scroll through conversations and contacts.
|
||||
CustomEvents.define(this.messageArea.find(SELECTORS.CONVERSATIONS), [
|
||||
CustomEvents.events.scrollBottom
|
||||
]);
|
||||
CustomEvents.define(this.messageArea.find(SELECTORS.CONTACTS), [
|
||||
CustomEvents.events.scrollBottom
|
||||
]);
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.scrollBottom, SELECTORS.CONVERSATIONS,
|
||||
this._loadConversations.bind(this));
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.scrollBottom, SELECTORS.CONTACTS,
|
||||
this._loadContacts.bind(this));
|
||||
|
||||
if (!this.messageArea.showContactsFirst()) {
|
||||
// Set the initial number of conversations to retrieve. Otherwise it will display no conversations.
|
||||
this._numConversationsDisplayed = 20;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Turn on deleting.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Contacts.prototype._startDeleting = function() {
|
||||
this.messageArea.find(SELECTORS.CONTACTSAREA).addClass('editing');
|
||||
};
|
||||
|
||||
/**
|
||||
* Turn off deleting.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Contacts.prototype._stopDeleting = function() {
|
||||
this.messageArea.find(SELECTORS.CONTACTSAREA).removeClass('editing');
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles viewing the list of conversations.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Contacts.prototype._viewConversations = function() {
|
||||
// If conversations is empty then try load some.
|
||||
if (this._numConversationsDisplayed === 0) {
|
||||
this._loadConversations();
|
||||
}
|
||||
|
||||
this.messageArea.find(SELECTORS.CONTACTS).hide();
|
||||
this.messageArea.find(SELECTORS.CONVERSATIONS).show();
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles viewing the list of contacts.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Contacts.prototype._viewContacts = function() {
|
||||
// If contacts is empty then try load some.
|
||||
if (this._numContactsDisplayed === 0) {
|
||||
this._loadContacts();
|
||||
}
|
||||
|
||||
this.messageArea.find(SELECTORS.CONVERSATIONS).hide();
|
||||
this.messageArea.find(SELECTORS.CONTACTS).show();
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles when a message is sent.
|
||||
*
|
||||
* @param {Event} event The message sent event
|
||||
* @param {int} userid The id of the user who the message was sent to
|
||||
* @param {String} text The message text
|
||||
* @private
|
||||
*/
|
||||
Contacts.prototype._handleMessageSent = function(event, userid, text) {
|
||||
// Switch to viewing the conversations.
|
||||
this._viewConversations();
|
||||
// Get the user node.
|
||||
var user = this._getUserNode(SELECTORS.CONVERSATIONS, userid);
|
||||
// If the user has not been loaded yet, let's copy the element from contact or search panel to the conversation panel.
|
||||
if (user.length === 0) {
|
||||
// Let's clone the data on the contact page.
|
||||
var usercontact = this._getUserNode(SELECTORS.CONTACTS, userid);
|
||||
if (usercontact.length === 0) {
|
||||
// No luck, maybe we sent the message to a user we searched for - check search page.
|
||||
usercontact = this._getUserNode(SELECTORS.SEARCHRESULTSAREA, userid);
|
||||
}
|
||||
if (usercontact.length == 0) {
|
||||
// Can't do much.
|
||||
return;
|
||||
}
|
||||
user = usercontact.clone();
|
||||
// Change the data action attribute.
|
||||
user.attr('data-action', 'view-contact-msg');
|
||||
// Remove the 'no conversations' message.
|
||||
this.messageArea.find(SELECTORS.CONVERSATIONS + " " +
|
||||
SELECTORS.NOCONTACTS).remove();
|
||||
// Increment the number of conversations displayed.
|
||||
this._numConversationsDisplayed++;
|
||||
}
|
||||
// Move the contact to the top of the list.
|
||||
user.prependTo(this.messageArea.find(SELECTORS.CONVERSATIONS));
|
||||
// Scroll to the top.
|
||||
this.messageArea.find(SELECTORS.CONVERSATIONS).scrollTop(0);
|
||||
// Get the new text to show.
|
||||
this._updateContactText(user, text, true);
|
||||
// Ensure user is selected.
|
||||
this._setSelectedUser("[data-userid='" + userid + "']");
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles loading conversations.
|
||||
*
|
||||
* @return {Promise|boolean} The promise resolved when the contact area has been rendered,
|
||||
* @private
|
||||
*/
|
||||
Contacts.prototype._loadConversations = function() {
|
||||
if (this._isLoadingConversations) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Tell the user we are loading items.
|
||||
this._isLoadingConversations = true;
|
||||
|
||||
// Keep track of the number of contacts
|
||||
var numberreceived = 0;
|
||||
// Add loading icon to the end of the list.
|
||||
return Templates.render('core/loading', {}).then(function(html, js) {
|
||||
if (this._numConversationsDisplayed) {
|
||||
Templates.appendNodeContents(this.messageArea.find(SELECTORS.CONVERSATIONS),
|
||||
"<div style='text-align:center'>" + html + "</div>", js);
|
||||
} else { // No conversations, just replace contents.
|
||||
Templates.replaceNodeContents(this.messageArea.find(SELECTORS.CONVERSATIONS),
|
||||
"<div style='text-align:center'>" + html + "</div>", js);
|
||||
}
|
||||
return this._getItems('core_message_data_for_messagearea_conversations',
|
||||
this._numConversationsDisplayed, this._numConversationsToRetrieve);
|
||||
}.bind(this)).then(function(data) {
|
||||
numberreceived = data.contacts.length;
|
||||
data.isconversation = true;
|
||||
return Templates.render('core_message/message_area_contacts', data);
|
||||
}).then(function(html, js) {
|
||||
// Remove the loading icon.
|
||||
this.messageArea.find(SELECTORS.CONVERSATIONS + " " +
|
||||
SELECTORS.LOADINGICON).remove();
|
||||
// Only append data if we got data back.
|
||||
if (numberreceived > 0) {
|
||||
// Show the new content.
|
||||
Templates.appendNodeContents(this.messageArea.find(SELECTORS.CONVERSATIONS), html, js);
|
||||
// Increment the number of conversations displayed. We increment by the number of conversations we
|
||||
// asked to retrieve not by the number that was actually retrieved, see MDL-55870.
|
||||
this._numConversationsDisplayed += this._numConversationsToRetrieve;
|
||||
} else if (!this._numConversationsDisplayed) {
|
||||
// If we didn't receive any contacts and there are currently none, then we want to show a message.
|
||||
Templates.replaceNodeContents(this.messageArea.find(SELECTORS.CONVERSATIONS), html, js);
|
||||
}
|
||||
// Mark that we are no longer busy loading data.
|
||||
this._isLoadingConversations = false;
|
||||
}.bind(this)).fail(Notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles loading contacts.
|
||||
*
|
||||
* @return {Promise|boolean} The promise resolved when the contact area has been rendered
|
||||
* @private
|
||||
*/
|
||||
Contacts.prototype._loadContacts = function() {
|
||||
if (this._isLoadingContacts) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Tell the user we are loading items.
|
||||
this._isLoadingContacts = true;
|
||||
|
||||
// Keep track of the number of contacts
|
||||
var numberreceived = 0;
|
||||
// Add loading icon to the end of the list.
|
||||
return Templates.render('core/loading', {}).then(function(html, js) {
|
||||
if (this._numContactsDisplayed) {
|
||||
Templates.appendNodeContents(this.messageArea.find(SELECTORS.CONTACTS),
|
||||
"<div style='text-align:center'>" + html + "</div>", js);
|
||||
} else { // No contacts, just replace contents.
|
||||
Templates.replaceNodeContents(this.messageArea.find(SELECTORS.CONTACTS),
|
||||
"<div style='text-align:center'>" + html + "</div>", js);
|
||||
}
|
||||
return this._getItems('core_message_data_for_messagearea_contacts',
|
||||
this._numContactsDisplayed, this._numContactsToRetrieve);
|
||||
}.bind(this)).then(function(data) {
|
||||
numberreceived = data.contacts.length;
|
||||
data.isconversation = false;
|
||||
return Templates.render('core_message/message_area_contacts', data);
|
||||
}).then(function(html, js) {
|
||||
// Remove the loading icon.
|
||||
this.messageArea.find(SELECTORS.CONTACTS + " " +
|
||||
SELECTORS.LOADINGICON).remove();
|
||||
// Only append data if we got data back.
|
||||
if (numberreceived > 0) {
|
||||
// Show the new content.
|
||||
Templates.appendNodeContents(this.messageArea.find(SELECTORS.CONTACTS), html, js);
|
||||
// Increment the number of contacts displayed.
|
||||
this._numContactsDisplayed += numberreceived;
|
||||
} else if (!this._numContactsDisplayed) {
|
||||
// If we didn't receive any contacts and there are currently none, then we want to show a message.
|
||||
Templates.replaceNodeContents(this.messageArea.find(SELECTORS.CONTACTS), html, js);
|
||||
}
|
||||
// Mark that we are no longer busy loading data.
|
||||
this._isLoadingContacts = false;
|
||||
}.bind(this)).fail(Notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles viewing a particular conversation.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @private
|
||||
*/
|
||||
Contacts.prototype._viewConversation = function(event) {
|
||||
// Cancel any deletion of messages we may have.
|
||||
this.messageArea.trigger(Events.CANCELDELETEMESSAGES);
|
||||
|
||||
var userid = $(event.currentTarget).data('userid');
|
||||
var messageid = $(event.currentTarget).data('messageid');
|
||||
var selector = "[data-userid='" + userid + "']";
|
||||
// If we have a specific message id then we did a search and the contact may appear in multiple
|
||||
// places - we don't want to highlight them all.
|
||||
if (messageid) {
|
||||
selector = "[data-messageid='" + messageid + "']";
|
||||
}
|
||||
|
||||
this._setSelectedUser(selector);
|
||||
this.messageArea.trigger(Events.CONVERSATIONSELECTED, userid);
|
||||
// Don't highlight the contact because the message region has changed.
|
||||
this.messageArea.find(SELECTORS.SELECTEDVIEWPROFILE).removeClass('selected');
|
||||
this._showMessagingArea();
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles viewing a particular contact.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @private
|
||||
*/
|
||||
Contacts.prototype._viewContact = function(event) {
|
||||
// Cancel any deletion of messages we may have.
|
||||
this.messageArea.trigger(Events.CANCELDELETEMESSAGES);
|
||||
|
||||
var userid = $(event.currentTarget).data('userid');
|
||||
this._setSelectedUser("[data-userid='" + userid + "']");
|
||||
this.messageArea.trigger(Events.CONTACTSELECTED, userid);
|
||||
// Don't highlight the conversation because the message region has changed.
|
||||
this.messageArea.find(SELECTORS.SELECTEDVIEWCONVERSATION).removeClass('selected');
|
||||
this._showMessagingArea();
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles returning a list of items to display.
|
||||
*
|
||||
* @param {String} webservice The web service to call
|
||||
* @param {int} limitfrom
|
||||
* @param {int} limitnum
|
||||
* @return {Promise} The promise resolved when the contact area has been rendered
|
||||
* @private
|
||||
*/
|
||||
Contacts.prototype._getItems = function(webservice, limitfrom, limitnum) {
|
||||
// Call the web service to return the data we want to view.
|
||||
var promises = Ajax.call([{
|
||||
methodname: webservice,
|
||||
args: {
|
||||
userid: this.messageArea.getCurrentUserId(),
|
||||
limitfrom: limitfrom,
|
||||
limitnum: limitnum
|
||||
}
|
||||
}]);
|
||||
|
||||
return promises[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles deleting a conversation.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {int} userid The user id belonging to the messages we are deleting.
|
||||
* @private
|
||||
*/
|
||||
Contacts.prototype._deleteConversation = function(event, userid) {
|
||||
// Remove the conversation.
|
||||
this._removeContact(SELECTORS.CONVERSATIONS, userid);
|
||||
this._numConversationsDisplayed--;
|
||||
this._hideMessagingArea();
|
||||
// Now we have done all the deletion we can set the flag back to false.
|
||||
this._stopDeleting();
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles updating the last message in the contact.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {int} userid The user id belonging to the messages we are deleting
|
||||
* @param {jQuery|null} updatemessage The message we need to update the contact panel with
|
||||
* @private
|
||||
*/
|
||||
Contacts.prototype._updateLastMessage = function(event, userid, updatemessage) {
|
||||
// Check if the last message needs updating.
|
||||
if (updatemessage) {
|
||||
var user = this._getUserNode(SELECTORS.CONVERSATIONS, userid);
|
||||
var updatemessagetext = updatemessage.find(SELECTORS.MESSAGETEXT).text().trim();
|
||||
var sentbyuser = false;
|
||||
if (updatemessage.data('useridto') == userid) {
|
||||
// Must have been sent by the currently logged in user.
|
||||
sentbyuser = true;
|
||||
}
|
||||
|
||||
this._updateContactText(user, updatemessagetext, sentbyuser);
|
||||
}
|
||||
|
||||
// Now we have done all the deletion we can set the flag back to false.
|
||||
this._stopDeleting();
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles adding a contact to the list.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Contacts.prototype._addContact = function() {
|
||||
this.messageArea.find(SELECTORS.CONTACTS).empty();
|
||||
this._numContactsDisplayed = 0;
|
||||
this._loadContacts();
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles removing a contact from the list.
|
||||
*
|
||||
* @param {String} selector
|
||||
* @param {int} userid
|
||||
* @private
|
||||
*/
|
||||
Contacts.prototype._removeContact = function(selector, userid) {
|
||||
this._getUserNode(selector, userid).remove();
|
||||
this._numContactsDisplayed--;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles marking a contact as blocked on the list.
|
||||
*
|
||||
* @param {int} userid
|
||||
* @private
|
||||
*/
|
||||
Contacts.prototype._blockContact = function(userid) {
|
||||
var user = this._getUserNode(SELECTORS.CONTACTS, userid);
|
||||
user.find(SELECTORS.CONTACTICONBLOCKED).removeClass('hidden');
|
||||
|
||||
user = this._getUserNode(SELECTORS.CONVERSATIONS, userid);
|
||||
user.find(SELECTORS.CONTACTICONBLOCKED).removeClass('hidden');
|
||||
|
||||
user = this._getUserNode(SELECTORS.SEARCHRESULTSAREA, userid);
|
||||
user.find(SELECTORS.CONTACTICONBLOCKED).removeClass('hidden');
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles marking a contact as unblocked on the list.
|
||||
*
|
||||
* @param {int} userid
|
||||
* @private
|
||||
*/
|
||||
Contacts.prototype._unblockContact = function(userid) {
|
||||
var user = this._getUserNode(SELECTORS.CONTACTS, userid);
|
||||
user.find(SELECTORS.CONTACTICONBLOCKED).addClass('hidden');
|
||||
|
||||
user = this._getUserNode(SELECTORS.CONVERSATIONS, userid);
|
||||
user.find(SELECTORS.CONTACTICONBLOCKED).addClass('hidden');
|
||||
|
||||
user = this._getUserNode(SELECTORS.SEARCHRESULTSAREA, userid);
|
||||
user.find(SELECTORS.CONTACTICONBLOCKED).addClass('hidden');
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles retrieving a user node from a list.
|
||||
*
|
||||
* @param {String} selector
|
||||
* @param {int} userid
|
||||
* @return {jQuery} The user node
|
||||
* @private
|
||||
*/
|
||||
Contacts.prototype._getUserNode = function(selector, userid) {
|
||||
return this.messageArea.find(selector + " " + SELECTORS.CONTACT +
|
||||
"[data-userid='" + userid + "']");
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles selecting a contact in the list.
|
||||
*
|
||||
* @param {String} selector
|
||||
* @private
|
||||
*/
|
||||
Contacts.prototype._setSelectedUser = function(selector) {
|
||||
// Remove the 'selected' class from any other contact.
|
||||
this.messageArea.find(SELECTORS.CONTACT).removeClass('selected');
|
||||
this.messageArea.find(SELECTORS.CONTACT).attr('aria-pressed', false);
|
||||
// Set the tab for the user to selected.
|
||||
this.messageArea.find(SELECTORS.CONTACT + selector).addClass('selected');
|
||||
this.messageArea.find(SELECTORS.CONTACT + selector).attr('aria-pressed', true);
|
||||
};
|
||||
|
||||
/**
|
||||
* Converts a text message into the text that should be stored in the contact list
|
||||
*
|
||||
* @param {String} text
|
||||
* @return {String} The altered text
|
||||
*/
|
||||
Contacts.prototype._getContactText = function(text) {
|
||||
if (text.length > this._messageLength) {
|
||||
text = text.substr(0, this._messageLength - 3);
|
||||
text += '...';
|
||||
}
|
||||
|
||||
// Text node prevents script injection through HTML entities.
|
||||
return document.createTextNode(text);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles updating the contact text.
|
||||
*
|
||||
* @param {jQuery} user The user to update
|
||||
* @param {String} text The text to update the contact with
|
||||
* @param {Boolean} sentbyuser Was it sent by the currently logged in user?
|
||||
* @private
|
||||
*/
|
||||
Contacts.prototype._updateContactText = function(user, text, sentbyuser) {
|
||||
// Get the text we will display on the contact panel.
|
||||
text = this._getContactText(text);
|
||||
if (sentbyuser) {
|
||||
Str.get_string('you', 'message').done(function(string) {
|
||||
// Ensure we display that the message is from this user.
|
||||
user.find(SELECTORS.LASTMESSAGEUSER).empty().append(string);
|
||||
}).always(function() {
|
||||
user.find(SELECTORS.LASTMESSAGETEXT).empty().append(text);
|
||||
});
|
||||
} else {
|
||||
user.find(SELECTORS.LASTMESSAGEUSER).empty();
|
||||
user.find(SELECTORS.LASTMESSAGETEXT).empty().append(text);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Shifts focus to the next contact in the list.
|
||||
*
|
||||
* @param {event} e The jquery event
|
||||
* @param {object} data Additional event data
|
||||
*/
|
||||
Contacts.prototype._selectNextContact = function(e, data) {
|
||||
var contact = $(e.target).closest(SELECTORS.CONTACT);
|
||||
var next = contact.next();
|
||||
next.focus();
|
||||
|
||||
data.originalEvent.preventDefault();
|
||||
data.originalEvent.stopPropagation();
|
||||
};
|
||||
|
||||
/**
|
||||
* Shifts focus to the previous contact in the list.
|
||||
*
|
||||
* @param {event} e The jquery event
|
||||
* @param {object} data Additional event data
|
||||
*/
|
||||
Contacts.prototype._selectPreviousContact = function(e, data) {
|
||||
var contact = $(e.target).closest(SELECTORS.CONTACT);
|
||||
var previous = contact.prev();
|
||||
previous.focus();
|
||||
|
||||
data.originalEvent.preventDefault();
|
||||
data.originalEvent.stopPropagation();
|
||||
};
|
||||
|
||||
/**
|
||||
* Shifts focus to the next course in the list.
|
||||
*
|
||||
* @param {event} e The jquery event
|
||||
* @param {object} data Additional event data
|
||||
*/
|
||||
Contacts.prototype._selectNextCourse = function(e, data) {
|
||||
var course = $(e.target).closest(SELECTORS.COURSE);
|
||||
course.next().focus();
|
||||
|
||||
data.originalEvent.preventDefault();
|
||||
data.originalEvent.stopPropagation();
|
||||
};
|
||||
|
||||
/**
|
||||
* Shifts focus to the previous course in the list.
|
||||
*
|
||||
* @param {event} e The jquery event
|
||||
* @param {object} data Additional event data
|
||||
*/
|
||||
Contacts.prototype._selectPreviousCourse = function(e, data) {
|
||||
var course = $(e.target).closest(SELECTORS.COURSE);
|
||||
course.prev().focus();
|
||||
|
||||
data.originalEvent.preventDefault();
|
||||
data.originalEvent.stopPropagation();
|
||||
};
|
||||
|
||||
/**
|
||||
* Shifts focus to the next conversation in the list.
|
||||
*
|
||||
* @param {event} e The jquery event
|
||||
* @param {object} data Additional event data
|
||||
*/
|
||||
Contacts.prototype._selectNextConversation = function(e, data) {
|
||||
var conversation = $(e.target).closest(SELECTORS.VIEWCONVERSATION);
|
||||
var next = conversation.next();
|
||||
next.focus();
|
||||
|
||||
data.originalEvent.preventDefault();
|
||||
data.originalEvent.stopPropagation();
|
||||
};
|
||||
|
||||
/**
|
||||
* Shifts focus to the previous conversation in the list.
|
||||
*
|
||||
* @param {event} e The jquery event
|
||||
* @param {object} data Additional event data
|
||||
*/
|
||||
Contacts.prototype._selectPreviousConversation = function(e, data) {
|
||||
var conversation = $(e.target).closest(SELECTORS.VIEWCONVERSATION);
|
||||
var previous = conversation.prev();
|
||||
previous.focus();
|
||||
|
||||
data.originalEvent.preventDefault();
|
||||
data.originalEvent.stopPropagation();
|
||||
};
|
||||
|
||||
/**
|
||||
* Flags the search area as seaching.
|
||||
*/
|
||||
Contacts.prototype._setSearching = function() {
|
||||
$(SELECTORS.SEARCHTEXTAREA).addClass('searching');
|
||||
};
|
||||
|
||||
/**
|
||||
* Flags the search area as seaching.
|
||||
*/
|
||||
Contacts.prototype._clearSearching = function() {
|
||||
$(SELECTORS.SEARCHTEXTAREA).removeClass('searching');
|
||||
};
|
||||
|
||||
/**
|
||||
* Make the messaging area visible.
|
||||
*/
|
||||
Contacts.prototype._showMessagingArea = function() {
|
||||
this.messageArea.find(SELECTORS.MESSAGINGAREA)
|
||||
.removeClass('hide-messages')
|
||||
.addClass('show-messages');
|
||||
};
|
||||
|
||||
/**
|
||||
* Hide the messaging area.
|
||||
*/
|
||||
Contacts.prototype._hideMessagingArea = function() {
|
||||
this.messageArea.find(SELECTORS.MESSAGINGAREA)
|
||||
.removeClass('show-messages')
|
||||
.addClass('hide-messages');
|
||||
};
|
||||
|
||||
return Contacts;
|
||||
}
|
||||
);
|
@ -1,45 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* This module defines the events that are triggered in the message area.
|
||||
*
|
||||
* @module core_message/message_area_events
|
||||
* @package core_message
|
||||
* @copyright 2016 Mark Nelson <markn@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define([], function() {
|
||||
|
||||
/** @type {Object} The list of events triggered in the message area. */
|
||||
return {
|
||||
CANCELDELETEMESSAGES: 'cancel-delete-messages',
|
||||
CHOOSEMESSAGESTODELETE: 'choose-messages-to-delete',
|
||||
CONTACTADDED: 'contact-added',
|
||||
CONTACTBLOCKED: 'contact-blocked',
|
||||
CONTACTREMOVED: 'contact-removed',
|
||||
CONTACTSELECTED: 'contact-selected',
|
||||
CONTACTSSELECTED: 'contacts-selected',
|
||||
CONTACTUNBLOCKED: 'contact-unblocked',
|
||||
CONVERSATIONDELETED: 'conversation-deleted',
|
||||
CONVERSATIONSELECTED: 'conversation-selected',
|
||||
CONVERSATIONSSELECTED: 'conversations-selected',
|
||||
MESSAGESDELETED: 'messages-deleted',
|
||||
MESSAGESEARCHCANCELED: 'message-search-canceled',
|
||||
MESSAGESENT: 'message-sent',
|
||||
SENDMESSAGE: 'message-send',
|
||||
USERSSEARCHCANCELED: 'users-search-canceled'
|
||||
};
|
||||
});
|
@ -1,876 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* This module handles the message area of the messaging area.
|
||||
*
|
||||
* @module core_message/message_area_messages
|
||||
* @package core_message
|
||||
* @copyright 2016 Mark Nelson <markn@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/custom_interaction_events',
|
||||
'core/auto_rows', 'core_message/message_area_actions', 'core/modal_factory', 'core/modal_events',
|
||||
'core/str', 'core_message/message_area_events', 'core/backoff_timer'],
|
||||
function($, Ajax, Templates, Notification, CustomEvents, AutoRows, Actions, ModalFactory,
|
||||
ModalEvents, Str, Events, BackOffTimer) {
|
||||
|
||||
/** @type {int} The message area default height. */
|
||||
var MESSAGES_AREA_DEFAULT_HEIGHT = 500;
|
||||
|
||||
/** @type {int} The response default height. */
|
||||
var MESSAGES_RESPONSE_DEFAULT_HEIGHT = 50;
|
||||
|
||||
/** @type {Object} The list of selectors for the message area. */
|
||||
var SELECTORS = {
|
||||
BLOCKTIME: "[data-region='blocktime']",
|
||||
CANCELDELETEMESSAGES: "[data-action='cancel-delete-messages']",
|
||||
CONTACT: "[data-region='contact']",
|
||||
CONVERSATIONS: "[data-region='contacts'][data-region-content='conversations']",
|
||||
DELETEALLMESSAGES: "[data-action='delete-all-messages']",
|
||||
DELETEMESSAGES: "[data-action='delete-messages']",
|
||||
LOADINGICON: '.loading-icon',
|
||||
MESSAGE: "[data-region='message']",
|
||||
MESSAGERESPONSE: "[data-region='response']",
|
||||
MESSAGES: "[data-region='messages']",
|
||||
MESSAGESAREA: "[data-region='messages-area']",
|
||||
MESSAGINGAREA: "[data-region='messaging-area']",
|
||||
SENDMESSAGE: "[data-action='send-message']",
|
||||
SENDMESSAGETEXT: "[data-region='send-message-txt']",
|
||||
SHOWCONTACTS: "[data-action='show-contacts']",
|
||||
STARTDELETEMESSAGES: "[data-action='start-delete-messages']",
|
||||
};
|
||||
|
||||
/** @type {int} The number of milliseconds in a second. */
|
||||
var MILLISECONDSINSEC = 1000;
|
||||
|
||||
/**
|
||||
* Messages class.
|
||||
*
|
||||
* @param {Messagearea} messageArea The messaging area object.
|
||||
*/
|
||||
function Messages(messageArea) {
|
||||
this.messageArea = messageArea;
|
||||
this._init();
|
||||
}
|
||||
|
||||
/** @type {Boolean} checks if we are sending a message */
|
||||
Messages.prototype._isSendingMessage = false;
|
||||
|
||||
/** @type {Boolean} checks if we are currently loading messages */
|
||||
Messages.prototype._isLoadingMessages = false;
|
||||
|
||||
/** @type {int} the number of messagess displayed */
|
||||
Messages.prototype._numMessagesDisplayed = 0;
|
||||
|
||||
/** @type {array} the messages displayed or about to be displayed on the page */
|
||||
Messages.prototype._messageQueue = [];
|
||||
|
||||
/** @type {int} the number of messages to retrieve */
|
||||
Messages.prototype._numMessagesToRetrieve = 20;
|
||||
|
||||
/** @type {Modal} the confirmation modal */
|
||||
Messages.prototype._confirmationModal = null;
|
||||
|
||||
/** @type {int} the timestamp for the most recent visible message */
|
||||
Messages.prototype._latestMessageTimestamp = 0;
|
||||
|
||||
/** @type {BackOffTimer} the backoff timer */
|
||||
Messages.prototype._backoffTimer = null;
|
||||
|
||||
/** @type {Messagearea} The messaging area object. */
|
||||
Messages.prototype.messageArea = null;
|
||||
|
||||
/**
|
||||
* Initialise the event listeners.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._init = function() {
|
||||
CustomEvents.define(this.messageArea.node, [
|
||||
CustomEvents.events.activate,
|
||||
CustomEvents.events.up,
|
||||
CustomEvents.events.down,
|
||||
CustomEvents.events.enter,
|
||||
]);
|
||||
|
||||
// We have a responsive media query based on height that reduces this size on screens shorter than 670.
|
||||
if ($(window).height() <= 670) {
|
||||
MESSAGES_AREA_DEFAULT_HEIGHT = 400;
|
||||
}
|
||||
|
||||
AutoRows.init(this.messageArea.node);
|
||||
|
||||
this.messageArea.onCustomEvent(Events.CONVERSATIONSELECTED, this._viewMessages.bind(this));
|
||||
this.messageArea.onCustomEvent(Events.SENDMESSAGE, this._viewMessages.bind(this));
|
||||
this.messageArea.onCustomEvent(Events.CHOOSEMESSAGESTODELETE, this._chooseMessagesToDelete.bind(this));
|
||||
this.messageArea.onCustomEvent(Events.CANCELDELETEMESSAGES, this._hideDeleteAction.bind(this));
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.activate, SELECTORS.SENDMESSAGE,
|
||||
this._sendMessage.bind(this));
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.activate, SELECTORS.STARTDELETEMESSAGES,
|
||||
this._startDeleting.bind(this));
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.activate, SELECTORS.DELETEMESSAGES,
|
||||
this._deleteMessages.bind(this));
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.activate, SELECTORS.DELETEALLMESSAGES,
|
||||
this._deleteAllMessages.bind(this));
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.activate, SELECTORS.CANCELDELETEMESSAGES,
|
||||
this._triggerCancelMessagesToDelete.bind(this));
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.activate, SELECTORS.MESSAGE,
|
||||
this._toggleMessage.bind(this));
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.activate, SELECTORS.SHOWCONTACTS,
|
||||
this._hideMessagingArea.bind(this));
|
||||
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.up, SELECTORS.MESSAGE,
|
||||
this._selectPreviousMessage.bind(this));
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.down, SELECTORS.MESSAGE,
|
||||
this._selectNextMessage.bind(this));
|
||||
|
||||
this.messageArea.onDelegateEvent('focus', SELECTORS.SENDMESSAGETEXT, this._setMessaging.bind(this));
|
||||
this.messageArea.onDelegateEvent('blur', SELECTORS.SENDMESSAGETEXT, this._clearMessaging.bind(this));
|
||||
|
||||
$(document).on(AutoRows.events.ROW_CHANGE, this._adjustMessagesAreaHeight.bind(this));
|
||||
|
||||
// Check if any messages have been displayed on page load.
|
||||
var messages = this.messageArea.find(SELECTORS.MESSAGES);
|
||||
if (messages.length) {
|
||||
this._addScrollEventListener(messages.find(SELECTORS.MESSAGE).length);
|
||||
this._latestMessageTimestamp = messages.find(SELECTORS.MESSAGE + ':last').data('timecreated');
|
||||
}
|
||||
|
||||
// Create a timer to poll the server for new messages.
|
||||
this._backoffTimer = new BackOffTimer(this._loadNewMessages.bind(this),
|
||||
BackOffTimer.getIncrementalCallback(this.messageArea.pollmin * MILLISECONDSINSEC, MILLISECONDSINSEC,
|
||||
this.messageArea.pollmax * MILLISECONDSINSEC, this.messageArea.polltimeout * MILLISECONDSINSEC));
|
||||
|
||||
// Start the timer.
|
||||
this._backoffTimer.start();
|
||||
};
|
||||
|
||||
/**
|
||||
* View the message panel.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {int} userid
|
||||
* @return {Promise} The promise resolved when the messages have been loaded.
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._viewMessages = function(event, userid) {
|
||||
// We are viewing another user, or re-loading the panel, so set number of messages displayed to 0.
|
||||
this._numMessagesDisplayed = 0;
|
||||
// Stop the existing timer so we can set up the new user's messages.
|
||||
this._backoffTimer.stop();
|
||||
// Reset the latest timestamp when we change the messages view.
|
||||
this._latestMessageTimestamp = 0;
|
||||
|
||||
// Mark all the messages as read.
|
||||
var markMessagesAsRead = Ajax.call([{
|
||||
methodname: 'core_message_mark_all_messages_as_read',
|
||||
args: {
|
||||
useridto: this.messageArea.getCurrentUserId(),
|
||||
useridfrom: userid
|
||||
}
|
||||
}]);
|
||||
|
||||
// Keep track of the number of messages received.
|
||||
var numberreceived = 0;
|
||||
// Show loading template.
|
||||
return Templates.render('core/loading', {}).then(function(html, js) {
|
||||
Templates.replaceNodeContents(this.messageArea.find(SELECTORS.MESSAGESAREA), html, js);
|
||||
return markMessagesAsRead[0];
|
||||
}.bind(this)).then(function() {
|
||||
var conversationnode = this.messageArea.find(SELECTORS.CONVERSATIONS + " " +
|
||||
SELECTORS.CONTACT + "[data-userid='" + userid + "']");
|
||||
if (conversationnode.hasClass('unread')) {
|
||||
// Remove the class.
|
||||
conversationnode.removeClass('unread');
|
||||
// Trigger an event letting the notification popover (and whoever else) know.
|
||||
$(document).trigger('messagearea:conversationselected', userid);
|
||||
}
|
||||
return this._getMessages(userid);
|
||||
}.bind(this)).then(function(data) {
|
||||
numberreceived = data.messages.length;
|
||||
// We have the data - lets render the template with it.
|
||||
return Templates.render('core_message/message_area_messages_area', data);
|
||||
}).then(function(html, js) {
|
||||
Templates.replaceNodeContents(this.messageArea.find(SELECTORS.MESSAGESAREA), html, js);
|
||||
this._addScrollEventListener(numberreceived);
|
||||
// Restart the poll timer.
|
||||
this._backoffTimer.restart();
|
||||
this.messageArea.find(SELECTORS.SENDMESSAGETEXT).focus();
|
||||
}.bind(this)).fail(Notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Loads messages while scrolling.
|
||||
*
|
||||
* @return {Promise|boolean} The promise resolved when the messages have been loaded.
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._loadMessages = function() {
|
||||
if (this._isLoadingMessages) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this._isLoadingMessages = true;
|
||||
|
||||
// Keep track of the number of messages received.
|
||||
var numberreceived = 0;
|
||||
// Show loading template.
|
||||
return Templates.render('core/loading', {}).then(function(html, js) {
|
||||
Templates.prependNodeContents(this.messageArea.find(SELECTORS.MESSAGES),
|
||||
"<div style='text-align:center'>" + html + "</div>", js);
|
||||
return this._getMessages(this._getUserId());
|
||||
}.bind(this)).then(function(data) {
|
||||
numberreceived = data.messages.length;
|
||||
// We have the data - lets render the template with it.
|
||||
return Templates.render('core_message/message_area_messages', data);
|
||||
}).then(function(html, js) {
|
||||
// Remove the loading icon.
|
||||
this.messageArea.find(SELECTORS.MESSAGES + " " +
|
||||
SELECTORS.LOADINGICON).remove();
|
||||
// Check if we got something to do.
|
||||
if (numberreceived > 0) {
|
||||
var newHtml = $('<div>' + html + '</div>');
|
||||
if (this._hasMatchingBlockTime(this.messageArea.node, newHtml, true)) {
|
||||
this.messageArea.node.find(SELECTORS.BLOCKTIME + ':first').remove();
|
||||
}
|
||||
// Get height before we add the messages.
|
||||
var oldheight = this.messageArea.find(SELECTORS.MESSAGES)[0].scrollHeight;
|
||||
// Show the new content.
|
||||
Templates.prependNodeContents(this.messageArea.find(SELECTORS.MESSAGES), html, js);
|
||||
// Get height after we add the messages.
|
||||
var newheight = this.messageArea.find(SELECTORS.MESSAGES)[0].scrollHeight;
|
||||
// Make sure scroll bar is at the location before we loaded more messages.
|
||||
this.messageArea.find(SELECTORS.MESSAGES).scrollTop(newheight - oldheight);
|
||||
// Increment the number of messages displayed.
|
||||
this._numMessagesDisplayed += numberreceived;
|
||||
}
|
||||
// Mark that we are no longer busy loading data.
|
||||
this._isLoadingMessages = false;
|
||||
}.bind(this)).fail(Notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Loads and renders messages newer than the most recently seen messages.
|
||||
*
|
||||
* @return {Promise|boolean} The promise resolved when the messages have been loaded.
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._loadNewMessages = function() {
|
||||
if (this._isLoadingMessages) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we have no user id yet then bail early.
|
||||
if (!this._getUserId()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this._isLoadingMessages = true;
|
||||
|
||||
// Only scroll the message window if the user hasn't scrolled up.
|
||||
var shouldScrollBottom = false;
|
||||
var messages = this.messageArea.find(SELECTORS.MESSAGES);
|
||||
if (messages.length !== 0) {
|
||||
var scrollTop = messages.scrollTop();
|
||||
var innerHeight = messages.innerHeight();
|
||||
var scrollHeight = messages[0].scrollHeight;
|
||||
|
||||
if (scrollTop + innerHeight >= scrollHeight) {
|
||||
shouldScrollBottom = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Keep track of the number of messages received.
|
||||
return this._getMessages(this._getUserId(), true).then(function(data) {
|
||||
return this._addMessagesToDom(data.messages, shouldScrollBottom);
|
||||
}.bind(this)).always(function() {
|
||||
// Mark that we are no longer busy loading data.
|
||||
this._isLoadingMessages = false;
|
||||
}.bind(this)).fail(Notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles returning a list of messages to display.
|
||||
*
|
||||
* @param {int} userid
|
||||
* @param {bool} fromTimestamp Load messages from the latest known timestamp
|
||||
* @return {Promise} The promise resolved when the contact area has been rendered
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._getMessages = function(userid, fromTimestamp) {
|
||||
var args = {
|
||||
currentuserid: this.messageArea.getCurrentUserId(),
|
||||
otheruserid: userid,
|
||||
limitfrom: this._numMessagesDisplayed,
|
||||
limitnum: this._numMessagesToRetrieve,
|
||||
newest: true
|
||||
};
|
||||
|
||||
// If we're trying to load new messages since the message UI was
|
||||
// rendered. Used for ajax polling while user is on the message UI.
|
||||
if (fromTimestamp) {
|
||||
args.timefrom = this._latestMessageTimestamp;
|
||||
// Remove limit and offset. We want all new messages.
|
||||
args.limitfrom = 0;
|
||||
args.limitnum = 0;
|
||||
}
|
||||
|
||||
// Call the web service to get our data.
|
||||
var promises = Ajax.call([{
|
||||
methodname: 'core_message_data_for_messagearea_messages',
|
||||
args: args,
|
||||
}]);
|
||||
|
||||
// Do stuff when we get data back.
|
||||
return promises[0].then(function(data) {
|
||||
var messages = data.messages;
|
||||
|
||||
// Did we get any new messages?
|
||||
if (messages && messages.length) {
|
||||
var latestMessage = messages[messages.length - 1];
|
||||
|
||||
// Update our record of the latest known message for future requests.
|
||||
if (latestMessage.timecreated > this._latestMessageTimestamp) {
|
||||
// Next request should be for the second after the most recent message we've seen.
|
||||
this._latestMessageTimestamp = latestMessage.timecreated + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}.bind(this)).fail(function(ex) {
|
||||
// Stop the timer if we received an error so that we don't keep spamming the server.
|
||||
this._backoffTimer.stop();
|
||||
Notification.exception(ex);
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles sending a message.
|
||||
*
|
||||
* @return {Promise|boolean} The promise resolved once the message has been sent.
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._sendMessage = function() {
|
||||
var element = this.messageArea.find(SELECTORS.SENDMESSAGETEXT);
|
||||
var text = element.val().trim();
|
||||
|
||||
// Do not do anything if it is empty.
|
||||
if (text === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we are sending a message, don't do anything, be patient!
|
||||
if (this._isSendingMessage) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Ok, mark that we are sending a message.
|
||||
this._isSendingMessage = true;
|
||||
|
||||
// Call the web service to save our message.
|
||||
var promises = Ajax.call([{
|
||||
methodname: 'core_message_send_instant_messages',
|
||||
args: {
|
||||
messages: [
|
||||
{
|
||||
touserid: this._getUserId(),
|
||||
text: text
|
||||
}
|
||||
]
|
||||
}
|
||||
}]);
|
||||
|
||||
element.prop('disabled', true);
|
||||
|
||||
// Update the DOM when we get some data back.
|
||||
return promises[0].then(function(response) {
|
||||
if (response.length < 0) {
|
||||
// Even errors should return valid data.
|
||||
throw new Error('Invalid response');
|
||||
}
|
||||
if (response[0].errormessage) {
|
||||
throw new Error(response[0].errormessage);
|
||||
}
|
||||
// Fire an event to say the message was sent.
|
||||
this.messageArea.trigger(Events.MESSAGESENT, [this._getUserId(), text]);
|
||||
// Update the messaging area.
|
||||
return this._addLastMessageToDom();
|
||||
}.bind(this)).then(function() {
|
||||
// Ok, we are no longer sending a message.
|
||||
this._isSendingMessage = false;
|
||||
}.bind(this)).always(function() {
|
||||
element.prop('disabled', false);
|
||||
element.focus();
|
||||
}).fail(Notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles selecting messages to delete.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._chooseMessagesToDelete = function() {
|
||||
this.messageArea.find(SELECTORS.MESSAGESAREA).addClass('editing');
|
||||
this.messageArea.find(SELECTORS.MESSAGE)
|
||||
.attr('role', 'checkbox')
|
||||
.attr('aria-checked', 'false');
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles deleting messages.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._deleteMessages = function() {
|
||||
var userid = this.messageArea.getCurrentUserId();
|
||||
var checkboxes = this.messageArea.find(SELECTORS.MESSAGE + "[aria-checked='true']");
|
||||
var requests = [];
|
||||
var messagestoremove = [];
|
||||
|
||||
// Go through all the checked checkboxes and prepare them for deletion.
|
||||
checkboxes.each(function(id, element) {
|
||||
var node = $(element);
|
||||
var messageid = node.data('messageid');
|
||||
var isread = node.data('messageread') ? 1 : 0;
|
||||
messagestoremove.push(node);
|
||||
requests.push({
|
||||
methodname: 'core_message_delete_message',
|
||||
args: {
|
||||
messageid: messageid,
|
||||
userid: userid,
|
||||
read: isread
|
||||
}
|
||||
});
|
||||
});
|
||||
if (requests.length > 0) {
|
||||
$.when(Ajax.call(requests)).then(function() {
|
||||
// Store the last message on the page, and the last message being deleted.
|
||||
var updatemessage = null;
|
||||
var messages = this.messageArea.find(SELECTORS.MESSAGE);
|
||||
var lastmessage = messages.last();
|
||||
var lastremovedmessage = messagestoremove[messagestoremove.length - 1];
|
||||
// Remove the messages from the DOM.
|
||||
$.each(messagestoremove, function(key, message) {
|
||||
// Remove the message.
|
||||
message.remove();
|
||||
});
|
||||
// If the last message was deleted then we need to provide the new last message.
|
||||
if (lastmessage.data('id') === lastremovedmessage.data('id')) {
|
||||
updatemessage = this.messageArea.find(SELECTORS.MESSAGE).last();
|
||||
}
|
||||
// Now we have removed all the messages from the DOM lets remove any block times we may need to as well.
|
||||
$.each(messagestoremove, function(key, message) {
|
||||
// First - let's make sure there are no more messages in that time block.
|
||||
var blocktime = message.data('blocktime');
|
||||
if (this.messageArea.find(SELECTORS.MESSAGE +
|
||||
"[data-blocktime='" + blocktime + "']").length === 0) {
|
||||
this.messageArea.find(SELECTORS.BLOCKTIME +
|
||||
"[data-blocktime='" + blocktime + "']").remove();
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
// If there are no messages at all, then remove conversation panel.
|
||||
if (this.messageArea.find(SELECTORS.MESSAGE).length === 0) {
|
||||
this.messageArea.find(SELECTORS.CONVERSATIONS + " " +
|
||||
SELECTORS.CONTACT + "[data-userid='" + this._getUserId() + "']").remove();
|
||||
}
|
||||
|
||||
// Trigger event letting other modules know messages were deleted.
|
||||
this.messageArea.trigger(Events.MESSAGESDELETED, [this._getUserId(), updatemessage]);
|
||||
}.bind(this)).catch(Notification.exception);
|
||||
} else {
|
||||
// Trigger event letting other modules know messages were deleted.
|
||||
this.messageArea.trigger(Events.MESSAGESDELETED, this._getUserId());
|
||||
}
|
||||
|
||||
// Hide the items responsible for deleting messages.
|
||||
this._hideDeleteAction();
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles adding a scrolling event listener.
|
||||
*
|
||||
* @param {int} numberreceived The number of messages received
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._addScrollEventListener = function(numberreceived) {
|
||||
// Scroll to the bottom.
|
||||
this._scrollBottom();
|
||||
// Set the number of messages displayed.
|
||||
this._numMessagesDisplayed = numberreceived;
|
||||
// Now enable the ability to infinitely scroll through messages.
|
||||
CustomEvents.define(this.messageArea.find(SELECTORS.MESSAGES), [
|
||||
CustomEvents.events.scrollTop
|
||||
]);
|
||||
// Assign the event for scrolling.
|
||||
this.messageArea.onCustomEvent(CustomEvents.events.scrollTop, this._loadMessages.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles deleting a conversation.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._deleteAllMessages = function() {
|
||||
if (this._confirmationModal) {
|
||||
// Just show the existing modal.
|
||||
this._confirmationModal.show();
|
||||
return;
|
||||
}
|
||||
|
||||
var stringsPromise = Str.get_strings([
|
||||
{key: 'confirm'},
|
||||
{key: 'deleteallconfirm', component: 'message'},
|
||||
{key: 'delete'}
|
||||
]);
|
||||
var deleteModalPromise = ModalFactory.create(
|
||||
{
|
||||
type: ModalFactory.types.SAVE_CANCEL
|
||||
},
|
||||
this.messageArea.find(SELECTORS.DELETEALLMESSAGES)
|
||||
);
|
||||
|
||||
$.when(stringsPromise, deleteModalPromise).then(function(s, modal) {
|
||||
modal.setTitle(s[0]);
|
||||
modal.setBody(s[1]);
|
||||
modal.setSaveButtonText(s[2]);
|
||||
|
||||
this._confirmationModal = modal;
|
||||
// Only delete the conversation if the user agreed in the confirmation modal.
|
||||
modal.getRoot().on(ModalEvents.save, function() {
|
||||
var otherUserId = this._getUserId();
|
||||
var request = {
|
||||
methodname: 'core_message_delete_conversation',
|
||||
args: {
|
||||
userid: this.messageArea.getCurrentUserId(),
|
||||
otheruserid: otherUserId
|
||||
}
|
||||
};
|
||||
|
||||
// Delete the conversation.
|
||||
Ajax.call([request])[0].then(function() {
|
||||
// Clear the message area.
|
||||
this.messageArea.find(SELECTORS.MESSAGESAREA).empty();
|
||||
// Let the app know a conversation was deleted.
|
||||
this.messageArea.trigger(Events.CONVERSATIONDELETED, otherUserId);
|
||||
this._hideDeleteAction();
|
||||
}.bind(this)).catch(Notification.exception);
|
||||
}.bind(this));
|
||||
|
||||
// Display the confirmation.
|
||||
modal.show();
|
||||
}.bind(this)).catch(Notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles hiding the delete checkboxes and replacing the response area.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._hideDeleteAction = function() {
|
||||
this.messageArea.find(SELECTORS.MESSAGE)
|
||||
.removeAttr('role')
|
||||
.removeAttr('aria-checked');
|
||||
this.messageArea.find(SELECTORS.MESSAGESAREA).removeClass('editing');
|
||||
};
|
||||
|
||||
/**
|
||||
* Triggers the CANCELDELETEMESSAGES event.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._triggerCancelMessagesToDelete = function() {
|
||||
// Trigger event letting other modules know message deletion was canceled.
|
||||
this.messageArea.trigger(Events.CANCELDELETEMESSAGES);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles adding messages to the DOM.
|
||||
*
|
||||
* @param {array} messages An array of messages to be added to the DOM.
|
||||
* @param {boolean} shouldScrollBottom True will scroll to the bottom of the message window and show the new messages.
|
||||
* @return {Promise} The promise resolved when the messages have been added to the DOM.
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._addMessagesToDom = function(messages, shouldScrollBottom) {
|
||||
var numberreceived = 0;
|
||||
var messagesArea = this.messageArea.find(SELECTORS.MESSAGES);
|
||||
messages = messages.filter(function(message) {
|
||||
var id = "" + message.id + message.isread;
|
||||
// If the message is already queued to be rendered, remove from the list of messages.
|
||||
if (this._messageQueue[id]) {
|
||||
return false;
|
||||
}
|
||||
// Filter out any messages already rendered.
|
||||
var result = messagesArea.find(SELECTORS.MESSAGE + '[data-id="' + id + '"]');
|
||||
// Any message we are rendering should go in the messageQueue.
|
||||
if (!result.length) {
|
||||
this._messageQueue[id] = true;
|
||||
}
|
||||
return !result.length;
|
||||
}.bind(this));
|
||||
numberreceived = messages.length;
|
||||
// We have the data - lets render the template with it.
|
||||
return Templates.render('core_message/message_area_messages', {messages: messages}).then(function(html, js) {
|
||||
// Check if we got something to do.
|
||||
if (numberreceived > 0) {
|
||||
var newHtml = $('<div>' + html + '</div>');
|
||||
if (this._hasMatchingBlockTime(this.messageArea.node, newHtml, false)) {
|
||||
newHtml.find(SELECTORS.BLOCKTIME + ':first').remove();
|
||||
}
|
||||
// Show the new content.
|
||||
Templates.appendNodeContents(this.messageArea.find(SELECTORS.MESSAGES), newHtml, js);
|
||||
// Scroll the new message into view.
|
||||
if (shouldScrollBottom) {
|
||||
this._scrollBottom();
|
||||
}
|
||||
// Increment the number of messages displayed.
|
||||
this._numMessagesDisplayed += numberreceived;
|
||||
// Reset the poll timer because the user may be active.
|
||||
this._backoffTimer.restart();
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles adding the last message to the DOM.
|
||||
*
|
||||
* @return {Promise} The promise resolved when the message has been added to the DOM.
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._addLastMessageToDom = function() {
|
||||
// Call the web service to return how the message should look.
|
||||
var promises = Ajax.call([{
|
||||
methodname: 'core_message_data_for_messagearea_get_most_recent_message',
|
||||
args: {
|
||||
currentuserid: this.messageArea.getCurrentUserId(),
|
||||
otheruserid: this._getUserId()
|
||||
}
|
||||
}]);
|
||||
|
||||
// Add the message.
|
||||
return promises[0].then(function(data) {
|
||||
return this._addMessagesToDom([data], true);
|
||||
}.bind(this)).always(function() {
|
||||
// Empty the response text area.text
|
||||
this.messageArea.find(SELECTORS.SENDMESSAGETEXT).val('').trigger('input');
|
||||
}.bind(this)).fail(Notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the ID of the other user in the conversation.
|
||||
*
|
||||
* @return {int} The user id
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._getUserId = function() {
|
||||
return this.messageArea.find(SELECTORS.MESSAGES).data('userid');
|
||||
};
|
||||
|
||||
/**
|
||||
* Scrolls to the bottom of the messages.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._scrollBottom = function() {
|
||||
// Scroll to the bottom.
|
||||
var messages = this.messageArea.find(SELECTORS.MESSAGES);
|
||||
if (messages.length !== 0) {
|
||||
messages.scrollTop(messages[0].scrollHeight);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Select the previous message in the list.
|
||||
*
|
||||
* @param {event} e The jquery event
|
||||
* @param {object} data Extra event data
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._selectPreviousMessage = function(e, data) {
|
||||
var currentMessage = $(e.target).closest(SELECTORS.MESSAGE);
|
||||
|
||||
do {
|
||||
currentMessage = currentMessage.prev();
|
||||
} while (currentMessage.length && !currentMessage.is(SELECTORS.MESSAGE));
|
||||
|
||||
currentMessage.focus();
|
||||
|
||||
data.originalEvent.preventDefault();
|
||||
data.originalEvent.stopPropagation();
|
||||
};
|
||||
|
||||
/**
|
||||
* Select the next message in the list.
|
||||
*
|
||||
* @param {event} e The jquery event
|
||||
* @param {object} data Extra event data
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._selectNextMessage = function(e, data) {
|
||||
var currentMessage = $(e.target).closest(SELECTORS.MESSAGE);
|
||||
|
||||
do {
|
||||
currentMessage = currentMessage.next();
|
||||
} while (currentMessage.length && !currentMessage.is(SELECTORS.MESSAGE));
|
||||
|
||||
currentMessage.focus();
|
||||
|
||||
data.originalEvent.preventDefault();
|
||||
data.originalEvent.stopPropagation();
|
||||
};
|
||||
|
||||
/**
|
||||
* Flag the response area as messaging.
|
||||
*
|
||||
* @param {event} e The jquery event
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._setMessaging = function(e) {
|
||||
$(e.target).closest(SELECTORS.MESSAGERESPONSE).addClass('messaging');
|
||||
};
|
||||
|
||||
/**
|
||||
* Clear the response area as messaging flag.
|
||||
*
|
||||
* @param {event} e The jquery event
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._clearMessaging = function(e) {
|
||||
$(e.target).closest(SELECTORS.MESSAGERESPONSE).removeClass('messaging');
|
||||
};
|
||||
|
||||
/**
|
||||
* Turn on delete message mode.
|
||||
*
|
||||
* @param {event} e The jquery event
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._startDeleting = function(e) {
|
||||
var actions = new Actions(this.messageArea);
|
||||
actions.chooseMessagesToDelete();
|
||||
|
||||
e.preventDefault();
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if the message area is in editing mode.
|
||||
*
|
||||
* @return {bool}
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._isEditing = function() {
|
||||
return this.messageArea.find(SELECTORS.MESSAGESAREA).hasClass('editing');
|
||||
};
|
||||
|
||||
/**
|
||||
* Check or uncheck the message if the message area is in editing mode.
|
||||
*
|
||||
* @param {event} e The jquery event
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._toggleMessage = function(e) {
|
||||
if (!this._isEditing()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var message = $(e.target).closest(SELECTORS.MESSAGE);
|
||||
|
||||
if (message.attr('aria-checked') === 'true') {
|
||||
message.attr('aria-checked', 'false');
|
||||
} else {
|
||||
message.attr('aria-checked', 'true');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Adjust the height of the messages area to match the changed height of
|
||||
* the response area.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._adjustMessagesAreaHeight = function() {
|
||||
var messagesArea = this.messageArea.find(SELECTORS.MESSAGES);
|
||||
var messagesResponse = this.messageArea.find(SELECTORS.MESSAGERESPONSE);
|
||||
|
||||
var currentMessageResponseHeight = messagesResponse.outerHeight();
|
||||
var diffResponseHeight = currentMessageResponseHeight - MESSAGES_RESPONSE_DEFAULT_HEIGHT;
|
||||
var newMessagesAreaHeight = MESSAGES_AREA_DEFAULT_HEIGHT - diffResponseHeight;
|
||||
|
||||
messagesArea.outerHeight(newMessagesAreaHeight);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle the event that triggers sending a message from the messages area.
|
||||
*
|
||||
* @param {event} e The jquery event
|
||||
* @param {object} data Additional event data
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._sendMessageHandler = function(e, data) {
|
||||
data.originalEvent.preventDefault();
|
||||
|
||||
this._sendMessage();
|
||||
};
|
||||
|
||||
/**
|
||||
* Hide the messaging area. This only applies on smaller screen resolutions.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._hideMessagingArea = function() {
|
||||
this.messageArea.find(SELECTORS.MESSAGINGAREA)
|
||||
.removeClass('show-messages')
|
||||
.addClass('hide-messages');
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if a day separator needs to be removed.
|
||||
*
|
||||
* Example - scrolling up and loading previous messages that belong to the
|
||||
* same day as the last message that was previously shown, meaning we can
|
||||
* remove the original separator.
|
||||
*
|
||||
* @param {jQuery} domHtml The HTML in the DOM.
|
||||
* @param {jQuery} newHtml The HTML to compare to the DOM
|
||||
* @param {boolean} loadingPreviousMessages Are we loading previous messages?
|
||||
* @return {boolean}
|
||||
* @private
|
||||
*/
|
||||
Messages.prototype._hasMatchingBlockTime = function(domHtml, newHtml, loadingPreviousMessages) {
|
||||
var blockTime, blockTimePos, newBlockTime, newBlockTimePos;
|
||||
|
||||
if (loadingPreviousMessages) {
|
||||
blockTimePos = ':first';
|
||||
newBlockTimePos = ':last';
|
||||
} else {
|
||||
blockTimePos = ':last';
|
||||
newBlockTimePos = ':first';
|
||||
}
|
||||
|
||||
blockTime = domHtml.find(SELECTORS.BLOCKTIME + blockTimePos);
|
||||
newBlockTime = newHtml.find(SELECTORS.BLOCKTIME + newBlockTimePos);
|
||||
|
||||
if (blockTime.length && newBlockTime.length) {
|
||||
return blockTime.data('blocktime') == newBlockTime.data('blocktime');
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
return Messages;
|
||||
}
|
||||
);
|
@ -1,304 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* This module handles the profile area of the messaging area.
|
||||
*
|
||||
* @module core_message/message_area_profile
|
||||
* @package core_message
|
||||
* @copyright 2016 Mark Nelson <markn@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str', 'core/config',
|
||||
'core/custom_interaction_events', 'core_message/message_area_events'],
|
||||
function($, Ajax, Templates, Notification, Str, Config, CustomEvents, Events) {
|
||||
|
||||
/** @type {Object} The list of selectors for the message area. */
|
||||
var SELECTORS = {
|
||||
PROFILE: "[data-region='profile']",
|
||||
PROFILEADDCONTACT: "[data-action='profile-add-contact']",
|
||||
PROFILEBLOCKCONTACT: "[data-action='profile-block-contact']",
|
||||
PROFILEREMOVECONTACT: "[data-action='profile-remove-contact']",
|
||||
PROFILESENDMESSAGE: "[data-action='profile-send-message']",
|
||||
PROFILEUNBLOCKCONTACT: "[data-action='profile-unblock-contact']",
|
||||
PROFILEVIEW: "[data-action='profile-view']",
|
||||
SHOWCONTACTS: "[data-action='show-contacts']",
|
||||
MESSAGESAREA: "[data-region='messages-area']",
|
||||
MESSAGINGAREA: "[data-region='messaging-area']"
|
||||
};
|
||||
|
||||
/**
|
||||
* Profile class.
|
||||
*
|
||||
* @param {Messagearea} messageArea The messaging area object.
|
||||
*/
|
||||
function Profile(messageArea) {
|
||||
this.messageArea = messageArea;
|
||||
this._init();
|
||||
}
|
||||
|
||||
/** @type {Messagearea} The messaging area object. */
|
||||
Profile.prototype.messageArea = null;
|
||||
|
||||
/**
|
||||
* Initialise the event listeners.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Profile.prototype._init = function() {
|
||||
CustomEvents.define(this.messageArea.node, [
|
||||
CustomEvents.events.activate
|
||||
]);
|
||||
|
||||
this.messageArea.onCustomEvent(Events.CONTACTSELECTED, this._viewProfile.bind(this));
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.activate, SELECTORS.PROFILEVIEW,
|
||||
function(e, data) {
|
||||
this._viewFullProfile();
|
||||
data.originalEvent.preventDefault();
|
||||
}.bind(this));
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.activate, SELECTORS.PROFILESENDMESSAGE,
|
||||
function(e, data) {
|
||||
this._sendMessage();
|
||||
data.originalEvent.preventDefault();
|
||||
}.bind(this));
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.activate, SELECTORS.PROFILEUNBLOCKCONTACT,
|
||||
function(e, data) {
|
||||
this._unblockContact();
|
||||
data.originalEvent.preventDefault();
|
||||
}.bind(this));
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.activate, SELECTORS.PROFILEBLOCKCONTACT,
|
||||
function(e, data) {
|
||||
this._blockContact();
|
||||
data.originalEvent.preventDefault();
|
||||
}.bind(this));
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.activate, SELECTORS.PROFILEADDCONTACT,
|
||||
function(e, data) {
|
||||
this._addContact();
|
||||
data.originalEvent.preventDefault();
|
||||
}.bind(this));
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.activate, SELECTORS.PROFILEREMOVECONTACT,
|
||||
function(e, data) {
|
||||
this._removeContact();
|
||||
data.originalEvent.preventDefault();
|
||||
}.bind(this));
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.activate, SELECTORS.SHOWCONTACTS,
|
||||
this._hideMessagingArea.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles viewing the profile.
|
||||
*
|
||||
* @param {Event} event
|
||||
* @param {int} userid
|
||||
* @return {Promise} The promise resolved when the profile has been rendered
|
||||
* @private
|
||||
*/
|
||||
Profile.prototype._viewProfile = function(event, userid) {
|
||||
// Show loading template.
|
||||
Templates.render('core/loading', {}).done(function(html, js) {
|
||||
Templates.replaceNodeContents(this.messageArea.find(SELECTORS.MESSAGESAREA), html, js);
|
||||
}.bind(this));
|
||||
|
||||
// Call the web service to return the profile.
|
||||
var promises = Ajax.call([{
|
||||
methodname: 'core_message_data_for_messagearea_get_profile',
|
||||
args: {
|
||||
currentuserid: this.messageArea.getCurrentUserId(),
|
||||
otheruserid: userid
|
||||
}
|
||||
}]);
|
||||
|
||||
// Show the profile.
|
||||
return promises[0].then(function(data) {
|
||||
return Templates.render('core_message/message_area_profile', data);
|
||||
}).then(function(html, js) {
|
||||
Templates.replaceNodeContents(this.messageArea.find(SELECTORS.MESSAGESAREA), html, js);
|
||||
}.bind(this)).fail(Notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles viewing the user's full profile.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Profile.prototype._viewFullProfile = function() {
|
||||
window.location.href = Config.wwwroot + '/user/profile.php?id=' + this._getUserId();
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles viewing the messages with the user.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Profile.prototype._sendMessage = function() {
|
||||
this.messageArea.trigger(Events.SENDMESSAGE, this._getUserId());
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles blocking the contact.
|
||||
*
|
||||
* @return {Promise} The promise resolved when the contact has been blocked
|
||||
* @private
|
||||
*/
|
||||
Profile.prototype._blockContact = function() {
|
||||
var action = this._performAction('core_message_block_user', 'unblockcontact', 'profile-block-contact',
|
||||
'profile-unblock-contact', '');
|
||||
return action.then(function() {
|
||||
this.messageArea.trigger(Events.CONTACTBLOCKED, this._getUserId());
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles unblocking the contact.
|
||||
*
|
||||
* @return {Promise} The promise resolved when the contact has been unblocked
|
||||
* @private
|
||||
*/
|
||||
Profile.prototype._unblockContact = function() {
|
||||
var action = this._performAction('core_message_unblock_user', 'blockcontact', 'profile-unblock-contact',
|
||||
'profile-block-contact', 'danger');
|
||||
return action.then(function() {
|
||||
this.messageArea.trigger(Events.CONTACTUNBLOCKED, this._getUserId());
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles adding the contact.
|
||||
*
|
||||
* @return {Promise} The promise resolved when the contact has been added
|
||||
* @private
|
||||
*/
|
||||
Profile.prototype._addContact = function() {
|
||||
var action = this._performAction('core_message_create_contact_request', 'removecontact', 'profile-add-contact',
|
||||
'profile-remove-contact', 'danger');
|
||||
return action.then(function() {
|
||||
this.messageArea.trigger(Events.CONTACTADDED, this._getUserId());
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles removing the contact.
|
||||
*
|
||||
* @return {Promise} The promise resolved when the contact has been removed
|
||||
* @private
|
||||
*/
|
||||
Profile.prototype._removeContact = function() {
|
||||
var action = this._performAction('core_message_delete_contacts', 'addcontact', 'profile-remove-contact',
|
||||
'profile-add-contact', '');
|
||||
return action.then(function() {
|
||||
this.messageArea.trigger(Events.CONTACTREMOVED, this._getUserId());
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper function to perform actions on the profile page.
|
||||
*
|
||||
* @param {String} service The web service to call.
|
||||
* @param {String} string The string to change the button value to
|
||||
* @param {String} oldaction The data-action of the button
|
||||
* @param {string} newaction The data-action to change the button to
|
||||
* @param {String} newclass The CSS class we want to add
|
||||
* @return {Promise} The promise resolved when the action has been performed
|
||||
* @private
|
||||
*/
|
||||
Profile.prototype._performAction = function(service, string, oldaction, newaction, newclass) {
|
||||
// This is a temporary hack as we are getting rid of this UI.
|
||||
var userargs = '';
|
||||
switch (service) {
|
||||
case 'core_message_block_user':
|
||||
userargs = {
|
||||
userid: this.messageArea.getCurrentUserId(),
|
||||
blockeduserid: this._getUserId()
|
||||
};
|
||||
break;
|
||||
case 'core_message_unblock_user':
|
||||
userargs = {
|
||||
userid: this.messageArea.getCurrentUserId(),
|
||||
unblockeduserid: this._getUserId()
|
||||
};
|
||||
break;
|
||||
case 'core_message_create_contact_request':
|
||||
userargs = {
|
||||
userid: this.messageArea.getCurrentUserId(),
|
||||
requesteduserid: this._getUserId()
|
||||
};
|
||||
break;
|
||||
default:
|
||||
userargs = {
|
||||
userid: this.messageArea.getCurrentUserId(),
|
||||
userids: [
|
||||
this._getUserId()
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
var promises = Ajax.call([{
|
||||
methodname: service,
|
||||
args: userargs
|
||||
}]);
|
||||
|
||||
return promises[0].then(function() {
|
||||
return Str.get_string(string, 'message');
|
||||
}).then(function(s) {
|
||||
this._changeText(s, oldaction, newaction, newclass);
|
||||
}.bind(this)).fail(Notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Changes the text in the profile area.
|
||||
*
|
||||
* @param {String} text The string to change the button value to
|
||||
* @param {string} oldaction The data-action of the button
|
||||
* @param {string} newaction The data-action to change the button to
|
||||
* @param {String} newclass The CSS class we want to add
|
||||
* @private
|
||||
*/
|
||||
Profile.prototype._changeText = function(text, oldaction, newaction, newclass) {
|
||||
var anchor = this.messageArea.find("[data-action='" + oldaction + "']");
|
||||
// Change the text.
|
||||
anchor.text(text);
|
||||
// Remove any class.
|
||||
anchor.removeClass();
|
||||
// Add the class if there is one.
|
||||
if (newclass) {
|
||||
anchor.addClass(newclass);
|
||||
}
|
||||
|
||||
anchor.attr('data-action', newaction);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the ID of the user whos profile we are viewing.
|
||||
*
|
||||
* @return {int} The user ID
|
||||
* @private
|
||||
*/
|
||||
Profile.prototype._getUserId = function() {
|
||||
return this.messageArea.find(SELECTORS.PROFILE).data('userid');
|
||||
};
|
||||
|
||||
/**
|
||||
* Hide the messaging area. This only applies on smaller screen resolutions.
|
||||
*/
|
||||
Profile.prototype._hideMessagingArea = function() {
|
||||
this.messageArea.find(SELECTORS.MESSAGINGAREA)
|
||||
.removeClass('show-messages')
|
||||
.addClass('hide-messages');
|
||||
};
|
||||
|
||||
return Profile;
|
||||
}
|
||||
);
|
@ -1,425 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* The module handles searching contacts.
|
||||
*
|
||||
* @module core_message/message_area_search
|
||||
* @package core_message
|
||||
* @copyright 2016 Mark Nelson <markn@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str', 'core/custom_interaction_events',
|
||||
'core_message/message_area_events'],
|
||||
function($, Ajax, Templates, Notification, Str, CustomEvents, Events) {
|
||||
|
||||
/** @type {Object} The list of selectors for the message area. */
|
||||
var SELECTORS = {
|
||||
CONTACTS: "[data-region='contacts'][data-region-content='contacts']",
|
||||
CONTACTSAREA: "[data-region='contacts-area']",
|
||||
CONVERSATIONS: "[data-region='contacts'][data-region-content='conversations']",
|
||||
DELETESEARCHFILTER: "[data-region='search-filter-area']",
|
||||
LOADINGICON: '.loading-icon',
|
||||
SEARCHBOX: "[data-region='search-box']",
|
||||
SEARCHFILTER: "[data-region='search-filter']",
|
||||
SEARCHFILTERAREA: "[data-region='search-filter-area']",
|
||||
SEARCHRESULTSAREA: "[data-region='search-results-area']",
|
||||
SEARCHTEXTAREA: "[data-region='search-text-area']",
|
||||
SEARCHUSERSINCOURSE: "[data-action='search-users-in-course']",
|
||||
};
|
||||
|
||||
/**
|
||||
* Search class.
|
||||
*
|
||||
* @param {Messagearea} messageArea The messaging area object.
|
||||
*/
|
||||
function Search(messageArea) {
|
||||
this.messageArea = messageArea;
|
||||
this._init();
|
||||
}
|
||||
|
||||
/** @type {Messagearea} The messaging area object. */
|
||||
Search.prototype.messageArea = null;
|
||||
|
||||
/** @type {String} The area we are searching in. */
|
||||
Search.prototype._searchArea = null;
|
||||
|
||||
/** @type {String} The id of the course we are searching in (if any). */
|
||||
Search.prototype._courseid = null;
|
||||
|
||||
/** @type {Boolean} checks if we are currently loading */
|
||||
Search.prototype._isLoading = false;
|
||||
|
||||
/** @type {String} The number of messages displayed. */
|
||||
Search.prototype._numMessagesDisplayed = 0;
|
||||
|
||||
/** @type {String} The number of messages to retrieve. */
|
||||
Search.prototype._numMessagesToRetrieve = 20;
|
||||
|
||||
/** @type {String} The number of users displayed. */
|
||||
Search.prototype._numUsersDisplayed = 0;
|
||||
|
||||
/** @type {String} The number of users to retrieve. */
|
||||
Search.prototype._numUsersToRetrieve = 20;
|
||||
|
||||
/** @type {Array} The type of available search areas. **/
|
||||
Search.prototype._searchAreas = {
|
||||
MESSAGES: 'messages',
|
||||
USERS: 'users',
|
||||
USERSINCOURSE: 'usersincourse'
|
||||
};
|
||||
|
||||
/** @type {int} The timeout before performing an ajax search */
|
||||
Search.prototype._requestTimeout = null;
|
||||
|
||||
/**
|
||||
* Initialise the event listeners.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Search.prototype._init = function() {
|
||||
// Handle searching for text.
|
||||
this.messageArea.find(SELECTORS.SEARCHTEXTAREA).on('input', this._searchRequest.bind(this));
|
||||
|
||||
// Handle clicking on a course in the list of users.
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.activate, SELECTORS.SEARCHUSERSINCOURSE, function(e) {
|
||||
this._setFilter($(e.currentTarget).html());
|
||||
this._setPlaceholderText('searchforuser');
|
||||
this._clearSearchArea();
|
||||
this._searchArea = this._searchAreas.USERSINCOURSE;
|
||||
this._courseid = $(e.currentTarget).data('courseid');
|
||||
this._searchUsersInCourse();
|
||||
this.messageArea.find(SELECTORS.SEARCHBOX).focus();
|
||||
}.bind(this));
|
||||
|
||||
// Handle deleting the search filter.
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.activate, SELECTORS.DELETESEARCHFILTER, function() {
|
||||
this._hideSearchResults();
|
||||
// Filter has been removed, so we don't want to be searching in a course anymore.
|
||||
this._searchArea = this._searchAreas.USERS;
|
||||
this._setPlaceholderText('searchforuserorcourse');
|
||||
// Go back the contacts.
|
||||
this.messageArea.trigger(Events.USERSSEARCHCANCELED);
|
||||
this.messageArea.find(SELECTORS.SEARCHBOX).focus();
|
||||
}.bind(this));
|
||||
|
||||
// Handle events that occur outside this module.
|
||||
this.messageArea.onCustomEvent(Events.CONVERSATIONSSELECTED, function() {
|
||||
this._hideSearchResults();
|
||||
this._searchArea = this._searchAreas.MESSAGES;
|
||||
this._setPlaceholderText('searchmessages');
|
||||
}.bind(this));
|
||||
this.messageArea.onCustomEvent(Events.CONTACTSSELECTED, function() {
|
||||
this._hideSearchResults();
|
||||
this._searchArea = this._searchAreas.USERS;
|
||||
this._setPlaceholderText('searchforuserorcourse');
|
||||
}.bind(this));
|
||||
this.messageArea.onCustomEvent(Events.MESSAGESENT, function() {
|
||||
this._hideSearchResults();
|
||||
this._searchArea = this._searchAreas.MESSAGES;
|
||||
this._setPlaceholderText('searchmessages');
|
||||
}.bind(this));
|
||||
|
||||
// Event listeners for scrolling through messages and users in courses.
|
||||
CustomEvents.define(this.messageArea.find(SELECTORS.SEARCHRESULTSAREA), [
|
||||
CustomEvents.events.scrollBottom
|
||||
]);
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.scrollBottom, SELECTORS.SEARCHRESULTSAREA,
|
||||
function() {
|
||||
if (this._searchArea == this._searchAreas.MESSAGES) {
|
||||
this._searchMessages();
|
||||
} else if (this._searchArea == this._searchAreas.USERSINCOURSE) {
|
||||
this._searchUsersInCourse();
|
||||
}
|
||||
}.bind(this)
|
||||
);
|
||||
|
||||
// Set the initial search area.
|
||||
this._searchArea = (this.messageArea.showContactsFirst()) ? this._searchAreas.USERS : this._searchAreas.MESSAGES;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles when search requests are sent.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Search.prototype._searchRequest = function() {
|
||||
var str = this.messageArea.find(SELECTORS.SEARCHTEXTAREA + ' input').val();
|
||||
|
||||
if (this._requestTimeout) {
|
||||
clearTimeout(this._requestTimeout);
|
||||
}
|
||||
|
||||
if (str.trim() === '') {
|
||||
// If nothing we being searched then we need to display the usual data.
|
||||
if (this._searchArea == this._searchAreas.MESSAGES) {
|
||||
this._hideSearchResults();
|
||||
this.messageArea.trigger(Events.MESSAGESEARCHCANCELED);
|
||||
} else if (this._searchArea == this._searchAreas.USERS) {
|
||||
this._hideSearchResults();
|
||||
this.messageArea.trigger(Events.USERSSEARCHCANCELED);
|
||||
} else if (this._searchArea == this._searchAreas.USERSINCOURSE) {
|
||||
// We are still searching in a course, so need to list all the users again.
|
||||
this._clearSearchArea();
|
||||
this._searchUsersInCourse();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.messageArea.find(SELECTORS.CONVERSATIONS).hide();
|
||||
this.messageArea.find(SELECTORS.CONTACTS).hide();
|
||||
this.messageArea.find(SELECTORS.SEARCHRESULTSAREA).show();
|
||||
|
||||
if (this._searchArea == this._searchAreas.MESSAGES) {
|
||||
this._requestTimeout = setTimeout(function() {
|
||||
this._clearSearchArea();
|
||||
this._numMessagesDisplayed = 0;
|
||||
this._searchMessages();
|
||||
}.bind(this), 300);
|
||||
} else if (this._searchArea == this._searchAreas.USERSINCOURSE) {
|
||||
this._requestTimeout = setTimeout(function() {
|
||||
this._clearSearchArea();
|
||||
this._numUsersDisplayed = 0;
|
||||
this._searchUsersInCourse();
|
||||
}.bind(this), 300);
|
||||
} else { // Must be searching for users and courses
|
||||
this._requestTimeout = setTimeout(function() {
|
||||
this._clearSearchArea();
|
||||
this._numUsersDisplayed = 0;
|
||||
this._searchUsers();
|
||||
}.bind(this), 300);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles searching for messages.
|
||||
*
|
||||
* @private
|
||||
* @return {Promise|boolean} The promise resolved when the search area has been rendered
|
||||
*/
|
||||
Search.prototype._searchMessages = function() {
|
||||
if (this._isLoading) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var str = this.messageArea.find(SELECTORS.SEARCHBOX).val();
|
||||
|
||||
// Tell the user we are loading items.
|
||||
this._isLoading = true;
|
||||
|
||||
// Call the web service to get our data.
|
||||
var promises = Ajax.call([{
|
||||
methodname: 'core_message_data_for_messagearea_search_messages',
|
||||
args: {
|
||||
userid: this.messageArea.getCurrentUserId(),
|
||||
search: str,
|
||||
limitfrom: this._numMessagesDisplayed,
|
||||
limitnum: this._numMessagesToRetrieve
|
||||
}
|
||||
}]);
|
||||
|
||||
// Keep track of the number of messages
|
||||
var numberreceived = 0;
|
||||
// Add loading icon to the end of the list.
|
||||
return Templates.render('core/loading', {}).then(function(html, js) {
|
||||
Templates.appendNodeContents(this.messageArea.find(SELECTORS.SEARCHRESULTSAREA),
|
||||
"<div style='text-align:center'>" + html + "</div>", js);
|
||||
return promises[0];
|
||||
}.bind(this)).then(function(data) {
|
||||
numberreceived = data.contacts.length;
|
||||
return Templates.render('core_message/message_area_message_search_results', data);
|
||||
}).then(function(html, js) {
|
||||
// Remove the loading icon.
|
||||
this.messageArea.find(SELECTORS.SEARCHRESULTSAREA + " " +
|
||||
SELECTORS.LOADINGICON).remove();
|
||||
// Only append data if we got data back.
|
||||
if (numberreceived > 0) {
|
||||
// Show the new content.
|
||||
Templates.appendNodeContents(this.messageArea.find(SELECTORS.SEARCHRESULTSAREA), html, js);
|
||||
// Increment the number of contacts displayed.
|
||||
this._numMessagesDisplayed += numberreceived;
|
||||
} else if (this._numMessagesDisplayed == 0) { // Must have nothing to begin with.
|
||||
// Replace the new content.
|
||||
Templates.replaceNodeContents(this.messageArea.find(SELECTORS.SEARCHRESULTSAREA), html, js);
|
||||
}
|
||||
// Mark that we are no longer busy loading data.
|
||||
this._isLoading = false;
|
||||
}.bind(this)).fail(Notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles searching for users.
|
||||
*
|
||||
* @private
|
||||
* @return {Promise} The promise resolved when the search area has been rendered
|
||||
*/
|
||||
Search.prototype._searchUsers = function() {
|
||||
var str = this.messageArea.find(SELECTORS.SEARCHBOX).val();
|
||||
|
||||
// Call the web service to get our data.
|
||||
var promises = Ajax.call([{
|
||||
methodname: 'core_message_data_for_messagearea_search_users',
|
||||
args: {
|
||||
userid: this.messageArea.getCurrentUserId(),
|
||||
search: str,
|
||||
limitnum: this._numUsersToRetrieve
|
||||
}
|
||||
}]);
|
||||
|
||||
// Perform the search and replace the content.
|
||||
return Templates.render('core/loading', {}).then(function(html, js) {
|
||||
Templates.replaceNodeContents(this.messageArea.find(SELECTORS.SEARCHRESULTSAREA),
|
||||
"<div style='text-align:center'>" + html + "</div>", js);
|
||||
return promises[0];
|
||||
}.bind(this)).then(function(data) {
|
||||
if (data.contacts.length > 0) {
|
||||
data.hascontacts = true;
|
||||
}
|
||||
if (data.courses.length > 0) {
|
||||
data.hascourses = true;
|
||||
}
|
||||
if (data.noncontacts.length > 0) {
|
||||
data.hasnoncontacts = true;
|
||||
}
|
||||
return Templates.render('core_message/message_area_user_search_results', data);
|
||||
}).then(function(html, js) {
|
||||
Templates.replaceNodeContents(this.messageArea.find(SELECTORS.SEARCHRESULTSAREA), html, js);
|
||||
}.bind(this)).fail(Notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles searching for users in a course.
|
||||
*
|
||||
* @private
|
||||
* @return {Promise|boolean} The promise resolved when the search area has been rendered
|
||||
*/
|
||||
Search.prototype._searchUsersInCourse = function() {
|
||||
if (this._isLoading) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var str = this.messageArea.find(SELECTORS.SEARCHBOX).val();
|
||||
|
||||
// Tell the user we are loading items.
|
||||
this._isLoading = true;
|
||||
|
||||
// Call the web service to get our data.
|
||||
var promises = Ajax.call([{
|
||||
methodname: 'core_message_data_for_messagearea_search_users_in_course',
|
||||
args: {
|
||||
userid: this.messageArea.getCurrentUserId(),
|
||||
courseid: this._courseid,
|
||||
search: str,
|
||||
limitfrom: this._numUsersDisplayed,
|
||||
limitnum: this._numUsersToRetrieve
|
||||
}
|
||||
}]);
|
||||
|
||||
// Keep track of the number of contacts
|
||||
var numberreceived = 0;
|
||||
// Add loading icon to the end of the list.
|
||||
return Templates.render('core/loading', {}).then(function(html, js) {
|
||||
Templates.appendNodeContents(this.messageArea.find(SELECTORS.SEARCHRESULTSAREA),
|
||||
"<div style='text-align:center'>" + html + "</div>", js);
|
||||
return promises[0];
|
||||
}.bind(this)).then(function(data) {
|
||||
numberreceived = data.contacts.length;
|
||||
if (numberreceived > 0) {
|
||||
data.hascontacts = true;
|
||||
}
|
||||
return Templates.render('core_message/message_area_user_search_results', data);
|
||||
}).then(function(html, js) {
|
||||
// Remove the loading icon.
|
||||
this.messageArea.find(SELECTORS.SEARCHRESULTSAREA + " " +
|
||||
SELECTORS.LOADINGICON).remove();
|
||||
// Only append data if we got data back.
|
||||
if (numberreceived > 0) {
|
||||
// Show the new content.
|
||||
Templates.appendNodeContents(this.messageArea.find(SELECTORS.SEARCHRESULTSAREA), html, js);
|
||||
// Increment the number of contacts displayed.
|
||||
this._numUsersDisplayed += numberreceived;
|
||||
} else if (this._numUsersDisplayed == 0) { // Must have nothing to begin with.
|
||||
// Replace the new content.
|
||||
Templates.replaceNodeContents(this.messageArea.find(SELECTORS.SEARCHRESULTSAREA), html, js);
|
||||
}
|
||||
// Mark that we are no longer busy loading data.
|
||||
this._isLoading = false;
|
||||
}.bind(this)).fail(Notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets placeholder text for search input.
|
||||
*
|
||||
* @private
|
||||
* @param {String} text The placeholder text
|
||||
* @return {Promise} The promise resolved when the placeholder text has been set
|
||||
*/
|
||||
Search.prototype._setPlaceholderText = function(text) {
|
||||
return Str.get_string(text, 'message').then(function(s) {
|
||||
this.messageArea.find(SELECTORS.SEARCHTEXTAREA + ' input').attr('placeholder', s);
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets filter for search input.
|
||||
*
|
||||
* @private
|
||||
* @param {String} text The filter text
|
||||
*/
|
||||
Search.prototype._setFilter = function(text) {
|
||||
this.messageArea.find(SELECTORS.SEARCHBOX).val('');
|
||||
this.messageArea.find(SELECTORS.CONTACTSAREA).addClass('searchfilter');
|
||||
this.messageArea.find(SELECTORS.SEARCHFILTERAREA).show();
|
||||
this.messageArea.find(SELECTORS.SEARCHFILTER).html(text);
|
||||
Str.get_string('removecoursefilter', 'message', text).then(function(languagestring) {
|
||||
this.messageArea.find(SELECTORS.SEARCHFILTERAREA).attr('aria-label', languagestring);
|
||||
}.bind(this)).catch(Notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Hides filter for search input.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Search.prototype._clearFilters = function() {
|
||||
this.messageArea.find(SELECTORS.CONTACTSAREA).removeClass('searchfilter');
|
||||
this.messageArea.find(SELECTORS.SEARCHFILTER).empty();
|
||||
this.messageArea.find(SELECTORS.SEARCHFILTERAREA).hide();
|
||||
this.messageArea.find(SELECTORS.SEARCHFILTERAREA).removeAttr('aria-label');
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles clearing the search area.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Search.prototype._clearSearchArea = function() {
|
||||
this.messageArea.find(SELECTORS.SEARCHRESULTSAREA).empty();
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles hiding the search area.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Search.prototype._hideSearchResults = function() {
|
||||
this._clearFilters();
|
||||
this.messageArea.find(SELECTORS.SEARCHTEXTAREA + ' input').val('');
|
||||
this._clearSearchArea();
|
||||
this.messageArea.find(SELECTORS.SEARCHRESULTSAREA).hide();
|
||||
};
|
||||
|
||||
return Search;
|
||||
});
|
@ -1,161 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* This module handles the tabs of the messaging area.
|
||||
*
|
||||
* @module core_message/message_area_tabs
|
||||
* @package core_message
|
||||
* @copyright 2016 Mark Nelson <markn@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['core/custom_interaction_events', 'core_message/message_area_events'], function(CustomEvents, Events) {
|
||||
|
||||
/** @type {Object} The list of selectors for the message area. */
|
||||
var SELECTORS = {
|
||||
ACTIVECONTACTSTAB: "[data-region='contacts-area'] [role='tab'][aria-selected='true']",
|
||||
CONTACTSPANELS: "[data-region='contacts']",
|
||||
VIEWCONTACTS: "[data-action='contacts-view']",
|
||||
VIEWCONVERSATIONS: "[data-action='conversations-view']"
|
||||
};
|
||||
|
||||
/**
|
||||
* Tabs class.
|
||||
*
|
||||
* @param {Messagearea} messageArea The messaging area object.
|
||||
*/
|
||||
function Tabs(messageArea) {
|
||||
this.messageArea = messageArea;
|
||||
this._init();
|
||||
}
|
||||
|
||||
/** @type {Messagearea} The messaging area object. */
|
||||
Tabs.prototype.messageArea = null;
|
||||
|
||||
/**
|
||||
* Initialise the event listeners.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Tabs.prototype._init = function() {
|
||||
CustomEvents.define(this.messageArea.node, [
|
||||
CustomEvents.events.activate,
|
||||
CustomEvents.events.up,
|
||||
CustomEvents.events.down,
|
||||
CustomEvents.events.next,
|
||||
CustomEvents.events.previous,
|
||||
CustomEvents.events.ctrlPageUp,
|
||||
CustomEvents.events.ctrlPageDown,
|
||||
]);
|
||||
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.activate, SELECTORS.VIEWCONVERSATIONS,
|
||||
this._viewConversations.bind(this));
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.activate, SELECTORS.VIEWCONTACTS,
|
||||
this._viewContacts.bind(this));
|
||||
|
||||
// Change to the other tab if any arrow keys are pressed, since there are only two tabs.
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.up, SELECTORS.VIEWCONVERSATIONS,
|
||||
this._toggleTabs.bind(this));
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.down, SELECTORS.VIEWCONVERSATIONS,
|
||||
this._toggleTabs.bind(this));
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.next, SELECTORS.VIEWCONVERSATIONS,
|
||||
this._toggleTabs.bind(this));
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.previous, SELECTORS.VIEWCONVERSATIONS,
|
||||
this._toggleTabs.bind(this));
|
||||
// Change to the other tab if any arrow keys are pressed, since there are only two tabs.
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.up, SELECTORS.VIEWCONTACTS,
|
||||
this._toggleTabs.bind(this));
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.down, SELECTORS.VIEWCONTACTS,
|
||||
this._toggleTabs.bind(this));
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.next, SELECTORS.VIEWCONTACTS,
|
||||
this._toggleTabs.bind(this));
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.previous, SELECTORS.VIEWCONTACTS,
|
||||
this._toggleTabs.bind(this));
|
||||
// Tab panel keyboard handling.
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.ctrlPageUp, SELECTORS.CONTACTSPANELS,
|
||||
this._toggleTabs.bind(this));
|
||||
this.messageArea.onDelegateEvent(CustomEvents.events.ctrlPageDown, SELECTORS.CONTACTSPANELS,
|
||||
this._toggleTabs.bind(this));
|
||||
|
||||
this.messageArea.onCustomEvent(Events.MESSAGESENT, function() {
|
||||
this._selectTab(SELECTORS.VIEWCONVERSATIONS, SELECTORS.VIEWCONTACTS);
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles when the conversation tab is selected.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Tabs.prototype._viewConversations = function() {
|
||||
this.messageArea.trigger(Events.CONVERSATIONSSELECTED);
|
||||
this._selectTab(SELECTORS.VIEWCONVERSATIONS, SELECTORS.VIEWCONTACTS);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles when the contacts tab is selected.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Tabs.prototype._viewContacts = function() {
|
||||
this.messageArea.trigger(Events.CONTACTSSELECTED);
|
||||
this._selectTab(SELECTORS.VIEWCONTACTS, SELECTORS.VIEWCONVERSATIONS);
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets a tab to selected.
|
||||
*
|
||||
* @param {String} tabselect The name of the tab to select
|
||||
* @param {String} tabdeselect The name of the tab to deselect
|
||||
* @private
|
||||
*/
|
||||
Tabs.prototype._selectTab = function(tabselect, tabdeselect) {
|
||||
tabdeselect = this.messageArea.find(tabdeselect);
|
||||
tabdeselect.removeClass('selected');
|
||||
tabdeselect.attr('aria-selected', 'false');
|
||||
tabdeselect.attr('tabindex', '-1');
|
||||
|
||||
tabselect = this.messageArea.find(tabselect);
|
||||
tabselect.addClass('selected');
|
||||
tabselect.attr('aria-selected', 'true');
|
||||
tabselect.attr('tabindex', '0');
|
||||
};
|
||||
|
||||
/**
|
||||
* Change to the inactive tab.
|
||||
*
|
||||
* @param {event} e The javascript event
|
||||
* @param {object} data The additional event data
|
||||
* @private
|
||||
*/
|
||||
Tabs.prototype._toggleTabs = function(e, data) {
|
||||
var activeTab = this.messageArea.find(SELECTORS.ACTIVECONTACTSTAB);
|
||||
|
||||
if (activeTab.is(SELECTORS.VIEWCONVERSATIONS)) {
|
||||
this._viewContacts();
|
||||
} else {
|
||||
this._viewConversations();
|
||||
}
|
||||
|
||||
this.messageArea.find(SELECTORS.ACTIVECONTACTSTAB).focus();
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
data.originalEvent.preventDefault();
|
||||
data.originalEvent.stopPropagation();
|
||||
};
|
||||
|
||||
return Tabs;
|
||||
});
|
@ -1,125 +0,0 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* Controls the message preference page.
|
||||
*
|
||||
* @module core_message/message_preferences
|
||||
* @class message_preferences
|
||||
* @package message
|
||||
* @copyright 2016 Ryan Wyllie <ryan@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
define(['jquery', 'core/ajax', 'core/notification',
|
||||
'core_message/message_notification_preference', 'core/custom_interaction_events'],
|
||||
function($, Ajax, Notification, MessageNotificationPreference, CustomEvents) {
|
||||
|
||||
var SELECTORS = {
|
||||
PREFERENCE: '[data-state]',
|
||||
PREFERENCES_CONTAINER: '[data-region="preferences-container"]',
|
||||
CONTACTABLE_PRIVACY_CONTAINER: '[data-region="privacy-setting-container"]',
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor for the MessagePreferences.
|
||||
*
|
||||
* @param {object} element The root element for the message preferences
|
||||
*/
|
||||
var MessagePreferences = function(element) {
|
||||
this.root = $(element);
|
||||
this.userId = this.root.find(SELECTORS.PREFERENCES_CONTAINER).attr('data-user-id');
|
||||
|
||||
this.registerEventListeners();
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if the preferences have been disabled on this page.
|
||||
*
|
||||
* @method preferencesDisabled
|
||||
* @return {bool}
|
||||
*/
|
||||
MessagePreferences.prototype.preferencesDisabled = function() {
|
||||
return this.root.find(SELECTORS.PREFERENCES_CONTAINER).hasClass('disabled');
|
||||
};
|
||||
|
||||
/**
|
||||
* Update the contactable privacy user preference in the DOM and
|
||||
* send a request to update on the server.
|
||||
*
|
||||
* @return {Promise}
|
||||
* @method saveContactablePrivacySetting
|
||||
*/
|
||||
MessagePreferences.prototype.saveContactablePrivacySetting = function() {
|
||||
var container = this.root.find(SELECTORS.CONTACTABLE_PRIVACY_CONTAINER);
|
||||
var value = $("input[type='radio']:checked").val();
|
||||
|
||||
if (container.hasClass('loading')) {
|
||||
return $.Deferred().resolve();
|
||||
}
|
||||
|
||||
container.addClass('loading');
|
||||
|
||||
var request = {
|
||||
methodname: 'core_user_update_user_preferences',
|
||||
args: {
|
||||
userid: this.userId,
|
||||
preferences: [
|
||||
{
|
||||
type: container.attr('data-preference-key'),
|
||||
value: value,
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
return Ajax.call([request])[0]
|
||||
.fail(Notification.exception)
|
||||
.always(function() {
|
||||
container.removeClass('loading');
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Create all of the event listeners for the message preferences page.
|
||||
*
|
||||
* @method registerEventListeners
|
||||
*/
|
||||
MessagePreferences.prototype.registerEventListeners = function() {
|
||||
CustomEvents.define(this.root, [
|
||||
CustomEvents.events.activate
|
||||
]);
|
||||
|
||||
this.root.on('change', function(e) {
|
||||
// Add listener for privacy setting radio buttons change.
|
||||
if (e.target.name == 'message_blocknoncontacts') {
|
||||
this.saveContactablePrivacySetting();
|
||||
} else {
|
||||
// Add listener for processor preferences.
|
||||
if (!this.preferencesDisabled()) {
|
||||
var preferencesContainer = $(e.target).closest(SELECTORS.PREFERENCES_CONTAINER);
|
||||
var preferenceElement = $(e.target).closest(SELECTORS.PREFERENCE);
|
||||
var messagePreference = new MessageNotificationPreference(preferencesContainer, this.userId);
|
||||
|
||||
preferenceElement.addClass('loading');
|
||||
messagePreference.save().always(function() {
|
||||
preferenceElement.removeClass('loading');
|
||||
});
|
||||
}
|
||||
}
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
return MessagePreferences;
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user