MDL-54687 core_message: added search functionality
This commit is contained in:
@@ -114,6 +114,7 @@ $string['nomessages'] = 'No messages waiting';
|
||||
$string['nomessagesfound'] = 'No messages were found';
|
||||
$string['noreply'] = 'Do not reply to this message';
|
||||
$string['nosearchresults'] = 'There were no results from your search';
|
||||
$string['noncontacts'] = 'Non-contacts';
|
||||
$string['nonotifications'] = 'You have no notifications';
|
||||
$string['nonewnotifications'] = 'You have no new notifications';
|
||||
$string['notificationwindow'] = 'Notification window';
|
||||
@@ -149,6 +150,7 @@ $string['removefromyourcontacts'] = 'Remove from your contacts';
|
||||
$string['savemysettings'] = 'Save my settings';
|
||||
$string['search'] = 'Search';
|
||||
$string['searchforperson'] = 'Search for a person';
|
||||
$string['searchforpersonorcourse'] = 'Search for a person or course';
|
||||
$string['searchmessages'] = 'Search messages';
|
||||
$string['searchcombined'] = 'Search people and messages';
|
||||
$string['selectmessagestodelete'] = 'Select messages or conversations to delete';
|
||||
|
||||
@@ -651,6 +651,30 @@ $functions = array(
|
||||
'type' => 'read',
|
||||
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
|
||||
),
|
||||
'core_message_data_for_messagearea_search_messages' => array(
|
||||
'classname' => 'core_message_external',
|
||||
'methodname' => 'data_for_messagearea_search_messages',
|
||||
'classpath' => 'message/externallib.php',
|
||||
'description' => 'Retrieve the template data for searching for messages',
|
||||
'type' => 'read',
|
||||
'ajax' => true,
|
||||
),
|
||||
'core_message_data_for_messagearea_search_people' => array(
|
||||
'classname' => 'core_message_external',
|
||||
'methodname' => 'data_for_messagearea_search_people',
|
||||
'classpath' => 'message/externallib.php',
|
||||
'description' => 'Retrieve the template data for searching for people',
|
||||
'type' => 'read',
|
||||
'ajax' => true,
|
||||
),
|
||||
'core_message_data_for_messagearea_search_people_in_course' => array(
|
||||
'classname' => 'core_message_external',
|
||||
'methodname' => 'data_for_messagearea_search_people_in_course',
|
||||
'classpath' => 'message/externallib.php',
|
||||
'description' => 'Retrieve the template data for searching for people in a course',
|
||||
'type' => 'read',
|
||||
'ajax' => true,
|
||||
),
|
||||
'core_message_data_for_messagearea_conversations' => array(
|
||||
'classname' => 'core_message_external',
|
||||
'methodname' => 'data_for_messagearea_conversations',
|
||||
|
||||
@@ -22,9 +22,8 @@
|
||||
* @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_actions'],
|
||||
function($, Contacts, Messages, Profile, Tabs, Actions) {
|
||||
'core_message/message_area_profile', 'core_message/message_area_tabs', 'core_message/message_area_search'],
|
||||
function($, Contacts, Messages, Profile, Tabs, Search) {
|
||||
|
||||
/**
|
||||
* Messagearea class.
|
||||
@@ -48,6 +47,7 @@ define(['jquery', 'core_message/message_area_contacts', 'core_message/message_ar
|
||||
CONVERSATIONS: "[data-region='contacts'][data-region-content='conversations']",
|
||||
DELETEMESSAGES: "[data-action='delete-messages']",
|
||||
DELETEMESSAGECHECKBOX: "[data-region='delete-message-checkbox']",
|
||||
DELETESEARCHFILTER: "[data-action='search-filter-delete']",
|
||||
LASTMESSAGE: '.lastmessage',
|
||||
LOADINGICON: '.loading-icon',
|
||||
MENU: "[data-region='menu']",
|
||||
@@ -64,8 +64,12 @@ define(['jquery', 'core_message/message_area_contacts', 'core_message/message_ar
|
||||
PROFILESENDMESSAGE: "[data-action='profile-send-message']",
|
||||
PROFILEUNBLOCKCONTACT: "[data-action='profile-unblock-contact']",
|
||||
PROFILEVIEW: "[data-action='profile-view']",
|
||||
SEARCHAREA: "[data-region='search-area']",
|
||||
SEARCHBOX: "[data-region='search-box']",
|
||||
SEARCHFILTER: "[data-region='search-filter']",
|
||||
SEARCHFILTERAREA: "[data-region='search-filter-area']",
|
||||
SEARCHPEOPLEINCOURSE : "[data-action='search-people-in-course']",
|
||||
SEARCHRESULTSAREA: "[data-region='search-results-area']",
|
||||
SEARCHTEXTAREA: "[data-region='search-text-area']",
|
||||
SELECTEDVIEWPROFILE: "[data-action='view-contact-profile'].selected",
|
||||
SELECTEDVIEWCONVERSATION: "[data-action='view-contact-msg'].selected",
|
||||
SENDMESSAGE: "[data-action='send-message']",
|
||||
@@ -91,7 +95,9 @@ define(['jquery', 'core_message/message_area_contacts', 'core_message/message_ar
|
||||
CONVERSATIONSELECTED: 'conversation-selected',
|
||||
CONVERSATIONSSELECTED: 'conversations-selected',
|
||||
MESSAGESDELETED: 'messages-deleted',
|
||||
MESSAGESEARCHCANCELED: 'message-search-canceled',
|
||||
MESSAGESENT: 'message-sent',
|
||||
PEOPLESEARCHCANCELED: 'people-search-canceled',
|
||||
SENDMESSAGE: 'message-send'
|
||||
};
|
||||
|
||||
@@ -106,6 +112,7 @@ define(['jquery', 'core_message/message_area_contacts', 'core_message/message_ar
|
||||
new Messages(this);
|
||||
new Profile(this);
|
||||
new Tabs(this);
|
||||
new Search(this);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -73,6 +73,9 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/cust
|
||||
customEvents.events.up,
|
||||
]);
|
||||
|
||||
this.messageArea.onCustomEvent(this.messageArea.EVENTS.MESSAGESEARCHCANCELED, this._viewConversations.bind(this));
|
||||
this.messageArea.onCustomEvent(this.messageArea.EVENTS.PEOPLESEARCHCANCELED, this._viewContacts.bind(this));
|
||||
this.messageArea.onCustomEvent(this.messageArea.EVENTS.CONTACTSSELECTED, this._viewContacts.bind(this));
|
||||
this.messageArea.onCustomEvent(this.messageArea.EVENTS.CONVERSATIONSSELECTED, this._viewConversations.bind(this));
|
||||
this.messageArea.onCustomEvent(this.messageArea.EVENTS.CONTACTSSELECTED, this._viewContacts.bind(this));
|
||||
this.messageArea.onCustomEvent(this.messageArea.EVENTS.MESSAGESDELETED, this._deleteConversations.bind(this));
|
||||
@@ -180,7 +183,7 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/cust
|
||||
// Replace the text.
|
||||
user.find(this.messageArea.SELECTORS.LASTMESSAGE).empty().append(text);
|
||||
// Ensure user is selected.
|
||||
this._setSelectedUser(userid);
|
||||
this._setSelectedUser("[data-userid='" + userid + "']");
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -282,7 +285,15 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/cust
|
||||
Contacts.prototype._viewConversation = function(event) {
|
||||
if (!this._isDeleting) {
|
||||
var userid = $(event.currentTarget).data('userid');
|
||||
this._setSelectedUser(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(this.messageArea.EVENTS.CONVERSATIONSELECTED, userid);
|
||||
// Don't highlight the contact because the message region has changed.
|
||||
this.messageArea.find(this.messageArea.SELECTORS.SELECTEDVIEWPROFILE).removeClass('selected');
|
||||
@@ -298,7 +309,7 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/cust
|
||||
Contacts.prototype._viewContact = function(event) {
|
||||
if (!this._isDeleting) {
|
||||
var userid = $(event.currentTarget).data('userid');
|
||||
this._setSelectedUser(userid);
|
||||
this._setSelectedUser("[data-userid='" + userid + "']");
|
||||
this.messageArea.trigger(this.messageArea.EVENTS.CONTACTSELECTED, userid);
|
||||
// Don't highlight the conversation because the message region has changed.
|
||||
this.messageArea.find(this.messageArea.SELECTORS.SELECTEDVIEWCONVERSATION).removeClass('selected');
|
||||
@@ -448,14 +459,14 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/cust
|
||||
/**
|
||||
* Handles selecting a contact in the list.
|
||||
*
|
||||
* @param {int} userid
|
||||
* @param {String} selector
|
||||
* @private
|
||||
*/
|
||||
Contacts.prototype._setSelectedUser = function(userid) {
|
||||
Contacts.prototype._setSelectedUser = function(selector) {
|
||||
// Remove the 'selected' class from any other contact.
|
||||
this.messageArea.find(this.messageArea.SELECTORS.CONTACT).removeClass('selected');
|
||||
// Set the tab for the user to selected.
|
||||
this.messageArea.find(this.messageArea.SELECTORS.CONTACT + "[data-userid='" + userid + "']").addClass('selected');
|
||||
this.messageArea.find(this.messageArea.SELECTORS.CONTACT + selector).addClass('selected');
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -536,14 +547,14 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/cust
|
||||
* Flags the search area as seaching.
|
||||
*/
|
||||
Contacts.prototype._setSearching = function() {
|
||||
$(this.messageArea.SELECTORS.SEARCHAREA).addClass('searching');
|
||||
$(this.messageArea.SELECTORS.SEARCHTEXTAREA).addClass('searching');
|
||||
};
|
||||
|
||||
/**
|
||||
* Flags the search area as seaching.
|
||||
*/
|
||||
Contacts.prototype._clearSearching = function() {
|
||||
$(this.messageArea.SELECTORS.SEARCHAREA).removeClass('searching');
|
||||
$(this.messageArea.SELECTORS.SEARCHTEXTAREA).removeClass('searching');
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,387 @@
|
||||
// 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 <[email protected]>
|
||||
* @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'],
|
||||
function($, ajax, templates, notification, str, customEvents) {
|
||||
|
||||
/**
|
||||
* 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 people displayed. */
|
||||
Search.prototype._numPeopleDisplayed = 0;
|
||||
|
||||
/** @type {String} The number of people to retrieve. */
|
||||
Search.prototype._numPeopleToRetrieve = 20;
|
||||
|
||||
/** @type {Array} The type of available search areas. **/
|
||||
Search.prototype._searchAreas = {
|
||||
MESSAGES: 'messages',
|
||||
PEOPLE: 'people',
|
||||
PEOPLEINCOURSE: 'peopleincourse'
|
||||
};
|
||||
|
||||
/** @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(this.messageArea.SELECTORS.SEARCHTEXTAREA).on('input', this._searchRequest.bind(this));
|
||||
|
||||
// Handle clicking on a course in the list of people.
|
||||
this.messageArea.onDelegateEvent('click', this.messageArea.SELECTORS.SEARCHPEOPLEINCOURSE, function(e) {
|
||||
this._setFilter($(e.currentTarget).html());
|
||||
this._setPlaceholderText('searchforperson');
|
||||
this._clearSearchArea();
|
||||
this._searchArea = this._searchAreas.PEOPLEINCOURSE;
|
||||
this._courseid = $(e.currentTarget).data('courseid');
|
||||
this._searchPeopleInCourse();
|
||||
}.bind(this));
|
||||
|
||||
// Handle deleting the search filter.
|
||||
this.messageArea.onDelegateEvent('click', this.messageArea.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.PEOPLE;
|
||||
this._setPlaceholderText('searchforpersonorcourse');
|
||||
// Go back the contacts.
|
||||
this.messageArea.trigger(this.messageArea.EVENTS.PEOPLESEARCHCANCELED);
|
||||
}.bind(this));
|
||||
|
||||
// Handle events that occur outside this module.
|
||||
this.messageArea.onCustomEvent(this.messageArea.EVENTS.CONVERSATIONSSELECTED, function() {
|
||||
this._hideSearchResults();
|
||||
this._searchArea = this._searchAreas.MESSAGES;
|
||||
this._setPlaceholderText('searchmessages');
|
||||
}.bind(this));
|
||||
this.messageArea.onCustomEvent(this.messageArea.EVENTS.CONTACTSSELECTED, function() {
|
||||
this._hideSearchResults();
|
||||
this._searchArea = this._searchAreas.PEOPLE;
|
||||
this._setPlaceholderText('searchforpersonorcourse');
|
||||
}.bind(this));
|
||||
this.messageArea.onCustomEvent(this.messageArea.EVENTS.MESSAGESENT, function() {
|
||||
this._hideSearchResults();
|
||||
this._searchArea = this._searchAreas.MESSAGES;
|
||||
this._setPlaceholderText('searchmessages');
|
||||
}.bind(this));
|
||||
|
||||
// Event listeners for scrolling through messages and people in courses.
|
||||
customEvents.define(this.messageArea.SELECTORS.SEARCHRESULTSAREA, [
|
||||
customEvents.events.scrollBottom
|
||||
]);
|
||||
this.messageArea.onDelegateEvent(customEvents.events.scrollBottom, this.messageArea.SELECTORS.SEARCHRESULTSAREA,
|
||||
function() {
|
||||
if (this._searchArea == this._searchAreas.MESSAGES) {
|
||||
this._searchMessages();
|
||||
} else if (this._searchArea == this._searchAreas.PEOPLEINCOURSE) {
|
||||
this._searchPeopleInCourse();
|
||||
}
|
||||
}.bind(this)
|
||||
);
|
||||
|
||||
// Set the initial search area.
|
||||
this._searchArea = this._searchAreas.MESSAGES;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles when search requests are sent.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Search.prototype._searchRequest = function() {
|
||||
var str = this.messageArea.find(this.messageArea.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(this.messageArea.EVENTS.MESSAGESEARCHCANCELED);
|
||||
} else if (this._searchArea == this._searchAreas.PEOPLE) {
|
||||
this._hideSearchResults();
|
||||
this.messageArea.trigger(this.messageArea.EVENTS.PEOPLESEARCHCANCELED);
|
||||
} else if (this._searchArea == this._searchAreas.PEOPLEINCOURSE) {
|
||||
// We are still searching in a course, so need to list all the people again.
|
||||
this._clearSearchArea();
|
||||
this._searchPeopleInCourse();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
this.messageArea.find(this.messageArea.SELECTORS.CONVERSATIONS).hide();
|
||||
this.messageArea.find(this.messageArea.SELECTORS.CONTACTS).hide();
|
||||
this.messageArea.find(this.messageArea.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.PEOPLEINCOURSE) {
|
||||
this._requestTimeout = setTimeout(function () {
|
||||
this._clearSearchArea();
|
||||
this._numPeopleDisplayed = 0;
|
||||
this._searchPeopleInCourse();
|
||||
}.bind(this), 300);
|
||||
} else { // Must be searching for people and courses
|
||||
this._requestTimeout = setTimeout(function() {
|
||||
this._clearSearchArea();
|
||||
this._numPeopleDisplayed = 0;
|
||||
this._searchPeople();
|
||||
}.bind(this), 300);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles searching for messages.
|
||||
*
|
||||
* @private
|
||||
* @returns {Promise} The promise resolved when the search area has been rendered
|
||||
*/
|
||||
Search.prototype._searchMessages = function() {
|
||||
if (this._isLoading) {
|
||||
return;
|
||||
}
|
||||
|
||||
var str = this.messageArea.find(this.messageArea.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.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_contacts', data);
|
||||
}).then(function(html, js) {
|
||||
// Remove the loading icon.
|
||||
this.messageArea.find(this.messageArea.SELECTORS.SEARCHRESULTSAREA + " " +
|
||||
this.messageArea.SELECTORS.LOADINGICON).remove();
|
||||
// Only append data if we got data back.
|
||||
if (numberreceived > 0) {
|
||||
// Show the new content.
|
||||
templates.appendNodeContents(this.messageArea.SELECTORS.SEARCHRESULTSAREA, html, js);
|
||||
// Increment the number of contacts displayed.
|
||||
this._numMessagesDisplayed += numberreceived;
|
||||
}
|
||||
// Mark that we are no longer busy loading data.
|
||||
this._isLoading = false;
|
||||
}.bind(this)).fail(notification.exception);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Handles searching for people.
|
||||
*
|
||||
* @private
|
||||
* @returns {Promise} The promise resolved when the search area has been rendered
|
||||
*/
|
||||
Search.prototype._searchPeople = function() {
|
||||
var str = this.messageArea.find(this.messageArea.SELECTORS.SEARCHBOX).val();
|
||||
|
||||
// Call the web service to get our data.
|
||||
var promises = ajax.call([{
|
||||
methodname: 'core_message_data_for_messagearea_search_people',
|
||||
args: {
|
||||
userid: this.messageArea.getCurrentUserId(),
|
||||
search: str,
|
||||
limitnum: this._numPeopleToRetrieve
|
||||
}
|
||||
}]);
|
||||
|
||||
// Perform the search and replace the content.
|
||||
return templates.render('core/loading', {}).then(function(html, js) {
|
||||
templates.replaceNodeContents(this.messageArea.SELECTORS.SEARCHRESULTSAREA,
|
||||
"<div style='text-align:center'>" + html + "</div>", js);
|
||||
return promises[0];
|
||||
}.bind(this)).then(function(data) {
|
||||
return templates.render('core_message/message_area_people_search_results', data);
|
||||
}).then(function(html, js) {
|
||||
templates.replaceNodeContents(this.messageArea.SELECTORS.SEARCHRESULTSAREA, html, js);
|
||||
}.bind(this)).fail(notification.exception);
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles searching for people in a course.
|
||||
*
|
||||
* @private
|
||||
* @returns {Promise} The promise resolved when the search area has been rendered
|
||||
*/
|
||||
Search.prototype._searchPeopleInCourse = function() {
|
||||
if (this._isLoading) {
|
||||
return;
|
||||
}
|
||||
|
||||
var str = this.messageArea.find(this.messageArea.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_people_in_course',
|
||||
args: {
|
||||
userid: this.messageArea.getCurrentUserId(),
|
||||
courseid: this._courseid,
|
||||
search: str,
|
||||
limitfrom: this._numPeopleDisplayed,
|
||||
limitnum: this._numPeopleToRetrieve
|
||||
}
|
||||
}]);
|
||||
|
||||
// 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.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_people_search_results', data);
|
||||
}).then(function(html, js) {
|
||||
// Remove the loading icon.
|
||||
this.messageArea.find(this.messageArea.SELECTORS.SEARCHRESULTSAREA + " " +
|
||||
this.messageArea.SELECTORS.LOADINGICON).remove();
|
||||
// Only append data if we got data back.
|
||||
if (numberreceived > 0) {
|
||||
// Show the new content.
|
||||
templates.appendNodeContents(this.messageArea.SELECTORS.SEARCHRESULTSAREA, html, js);
|
||||
// Increment the number of contacts displayed.
|
||||
this._numPeopleDisplayed += numberreceived;
|
||||
}
|
||||
// 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(this.messageArea.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(this.messageArea.SELECTORS.SEARCHBOX).val('');
|
||||
this.messageArea.find(this.messageArea.SELECTORS.CONTACTSAREA).addClass('searchfilter');
|
||||
this.messageArea.find(this.messageArea.SELECTORS.SEARCHFILTERAREA).show();
|
||||
this.messageArea.find(this.messageArea.SELECTORS.SEARCHFILTER).html(text);
|
||||
};
|
||||
|
||||
/**
|
||||
* Hides filter for search input.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Search.prototype._clearFilters = function() {
|
||||
this.messageArea.find(this.messageArea.SELECTORS.CONTACTSAREA).removeClass('searchfilter');
|
||||
this.messageArea.find(this.messageArea.SELECTORS.SEARCHFILTER).empty();
|
||||
this.messageArea.find(this.messageArea.SELECTORS.SEARCHFILTERAREA).hide();
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles clearing the search area.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Search.prototype._clearSearchArea = function() {
|
||||
this.messageArea.find(this.messageArea.SELECTORS.SEARCHRESULTSAREA).empty();
|
||||
};
|
||||
|
||||
/**
|
||||
* Handles hiding the search area.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
Search.prototype._hideSearchResults = function() {
|
||||
this._clearFilters();
|
||||
this.messageArea.find(this.messageArea.SELECTORS.SEARCHTEXTAREA + ' input').val('');
|
||||
this._clearSearchArea();
|
||||
this.messageArea.find(this.messageArea.SELECTORS.SEARCHRESULTSAREA).hide();
|
||||
};
|
||||
|
||||
return Search;
|
||||
});
|
||||
@@ -36,6 +36,184 @@ defined('MOODLE_INTERNAL') || die();
|
||||
*/
|
||||
class api {
|
||||
|
||||
/**
|
||||
* Handles searching for messages in the message area.
|
||||
*
|
||||
* @param int $userid The user id doing the searching
|
||||
* @param string $search The string the user is searching
|
||||
* @param int $limitfrom
|
||||
* @param int $limitnum
|
||||
* @return \core_message\output\messagearea\message_search_results
|
||||
*/
|
||||
public static function search_messages($userid, $search, $limitfrom = 0, $limitnum = 0) {
|
||||
global $DB;
|
||||
|
||||
// Get the user fields we want.
|
||||
$ufields = \user_picture::fields('u', array('lastaccess'), 'userfrom_id', 'userfrom_');
|
||||
$ufields2 = \user_picture::fields('u2', array('lastaccess'), 'userto_id', 'userto_');
|
||||
|
||||
// Get all the messages for the user.
|
||||
$sql = "SELECT m.id, m.useridfrom, m.useridto, m.subject, m.fullmessage, m.fullmessagehtml, m.fullmessageformat,
|
||||
m.smallmessage, m.notification, m.timecreated, 0 as isread, $ufields, $ufields2
|
||||
FROM {message} m
|
||||
JOIN {user} u
|
||||
ON m.useridfrom = u.id
|
||||
JOIN {user} u2
|
||||
ON m.useridto = u2.id
|
||||
WHERE ((useridto = ? AND timeusertodeleted = 0)
|
||||
OR (useridfrom = ? AND timeuserfromdeleted = 0))
|
||||
AND notification = 0
|
||||
AND u.deleted = 0
|
||||
AND u2.deleted = 0
|
||||
AND " . $DB->sql_like('smallmessage', '?', false) . "
|
||||
UNION ALL
|
||||
SELECT mr.id, mr.useridfrom, mr.useridto, mr.subject, mr.fullmessage, mr.fullmessagehtml, mr.fullmessageformat,
|
||||
mr.smallmessage, mr.notification, mr.timecreated, 1 as isread, $ufields, $ufields2
|
||||
FROM {message_read} mr
|
||||
JOIN {user} u
|
||||
ON mr.useridfrom = u.id
|
||||
JOIN {user} u2
|
||||
ON mr.useridto = u2.id
|
||||
WHERE ((useridto = ? AND timeusertodeleted = 0)
|
||||
OR (useridfrom = ? AND timeuserfromdeleted = 0))
|
||||
AND notification = 0
|
||||
AND u.deleted = 0
|
||||
AND u2.deleted = 0
|
||||
AND " . $DB->sql_like('smallmessage', '?', false) . "
|
||||
ORDER BY timecreated DESC";
|
||||
$params = array($userid, $userid, '%' . $search . '%',
|
||||
$userid, $userid, '%' . $search . '%');
|
||||
|
||||
// Convert the messages into searchable contacts with their last message being the message that was searched.
|
||||
$contacts = array();
|
||||
if ($messages = $DB->get_records_sql($sql, $params, $limitfrom, $limitnum)) {
|
||||
foreach ($messages as $message) {
|
||||
$prefix = 'userfrom_';
|
||||
if ($userid == $message->useridfrom) {
|
||||
$prefix = 'userto_';
|
||||
// If it from the user, then mark it as read, even if it wasn't by the receiver.
|
||||
$message->isread = true;
|
||||
}
|
||||
$message->messageid = $message->id;
|
||||
$contacts[] = \core_message\helper::create_contact($message, $prefix);
|
||||
}
|
||||
}
|
||||
|
||||
return new \core_message\output\messagearea\message_search_results($userid, $contacts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles searching for people in a particular course in the message area.
|
||||
*
|
||||
* @param int $userid The user id doing the searching
|
||||
* @param int $courseid The id of the course we are searching in
|
||||
* @param string $search The string the user is searching
|
||||
* @param int $limitfrom
|
||||
* @param int $limitnum
|
||||
* @return \core_message\output\messagearea\people_search_results
|
||||
*/
|
||||
public static function search_people_in_course($userid, $courseid, $search, $limitfrom = 0, $limitnum = 0) {
|
||||
global $DB;
|
||||
|
||||
// Get all the users in the course.
|
||||
list($esql, $params) = get_enrolled_sql(\context_course::instance($courseid), '', 0, true);
|
||||
$sql = "SELECT u.*
|
||||
FROM {user} u
|
||||
JOIN ($esql) je ON je.id = u.id
|
||||
WHERE u.deleted = 0";
|
||||
// Add more conditions.
|
||||
$fullname = $DB->sql_fullname();
|
||||
$sql .= " AND u.id != :userid
|
||||
AND " . $DB->sql_like($fullname, ':search', false) . "
|
||||
ORDER BY " . $DB->sql_fullname();
|
||||
$params = array_merge(array('userid' => $userid, 'search' => '%' . $search . '%'), $params);
|
||||
|
||||
|
||||
// Convert all the user records into contacts.
|
||||
$contacts = array();
|
||||
if ($users = $DB->get_records_sql($sql, $params, $limitfrom, $limitnum)) {
|
||||
foreach ($users as $user) {
|
||||
$contacts[] = \core_message\helper::create_contact($user);
|
||||
}
|
||||
}
|
||||
|
||||
return new \core_message\output\messagearea\people_search_results($contacts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles searching for people in the message area.
|
||||
*
|
||||
* @param int $userid The user id doing the searching
|
||||
* @param string $search The string the user is searching
|
||||
* @param int $limitnum
|
||||
* @return \core_message\output\messagearea\people_search_results
|
||||
*/
|
||||
public static function search_people($userid, $search, $limitnum = 0) {
|
||||
global $CFG, $DB;
|
||||
|
||||
require_once($CFG->dirroot . '/lib/coursecatlib.php');
|
||||
|
||||
// Used to search for contacts.
|
||||
$fullname = $DB->sql_fullname();
|
||||
$ufields = \user_picture::fields('u', array('lastaccess'));
|
||||
|
||||
// Users not to include.
|
||||
$excludeusers = array($userid, $CFG->siteguest);
|
||||
list($exclude, $excludeparams) = $DB->get_in_or_equal($excludeusers, SQL_PARAMS_NAMED, 'param', false);
|
||||
|
||||
// Ok, let's search for contacts first.
|
||||
$contacts = array();
|
||||
$sql = "SELECT $ufields
|
||||
FROM {user} u
|
||||
JOIN {message_contacts} mc
|
||||
ON u.id = mc.contactid
|
||||
WHERE mc.userid = :userid
|
||||
AND u.deleted = 0
|
||||
AND u.confirmed = 1
|
||||
AND " . $DB->sql_like($fullname, ':search', false) . "
|
||||
AND u.id $exclude
|
||||
ORDER BY " . $DB->sql_fullname();
|
||||
if ($users = $DB->get_records_sql($sql, array('userid' => $userid, 'search' => '%' . $search . '%') +
|
||||
$excludeparams, 0, $limitnum)) {
|
||||
foreach ($users as $user) {
|
||||
$contacts[] = \core_message\helper::create_contact($user);
|
||||
}
|
||||
}
|
||||
|
||||
// Now, let's get the courses.
|
||||
$courses = array();
|
||||
if ($arrcourses = \coursecat::search_courses(array('search' => $search), array('limit' => $limitnum))) {
|
||||
foreach ($arrcourses as $course) {
|
||||
$data = new \stdClass();
|
||||
$data->id = $course->id;
|
||||
$data->shortname = $course->shortname;
|
||||
$data->fullname = $course->fullname;
|
||||
$courses[] = $data;
|
||||
}
|
||||
}
|
||||
|
||||
// Let's get those non-contacts. Toast them gears boi.
|
||||
$noncontacts = array();
|
||||
$sql = "SELECT $ufields
|
||||
FROM {user} u
|
||||
WHERE u.deleted = 0
|
||||
AND u.confirmed = 1
|
||||
AND " . $DB->sql_like($fullname, ':search', false) . "
|
||||
AND u.id $exclude
|
||||
AND u.id NOT IN (SELECT contactid
|
||||
FROM {message_contacts}
|
||||
WHERE userid = :userid)
|
||||
ORDER BY " . $DB->sql_fullname();
|
||||
if ($users = $DB->get_records_sql($sql, array('userid' => $userid, 'search' => '%' . $search . '%') +
|
||||
$excludeparams, 0, $limitnum)) {
|
||||
foreach ($users as $user) {
|
||||
$noncontacts[] = \core_message\helper::create_contact($user);
|
||||
}
|
||||
}
|
||||
|
||||
return new \core_message\output\messagearea\people_search_results($contacts, $courses, $noncontacts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the contacts and their conversation to display in the contacts area.
|
||||
*
|
||||
|
||||
@@ -122,9 +122,10 @@ class helper {
|
||||
* Helper function for creating a contact renderable.
|
||||
*
|
||||
* @param \stdClass $contact
|
||||
* @param string $prefix
|
||||
* @return \core_message\output\messagearea\contact
|
||||
*/
|
||||
public static function create_contact($contact) {
|
||||
public static function create_contact($contact, $prefix = '') {
|
||||
global $CFG, $PAGE;
|
||||
|
||||
// Variables to check if we consider this user online or not.
|
||||
@@ -135,7 +136,7 @@ class helper {
|
||||
$time = time() - $timetoshowusers;
|
||||
|
||||
// Create the data we are going to pass to the renderable.
|
||||
$userfields = \user_picture::unalias($contact, array('lastaccess'));
|
||||
$userfields = \user_picture::unalias($contact, array('lastaccess'), $prefix . 'id', $prefix);
|
||||
$data = new \stdClass();
|
||||
$data->userid = $userfields->id;
|
||||
$data->fullname = fullname($userfields);
|
||||
@@ -146,10 +147,13 @@ class helper {
|
||||
$userpicture->size = 0; // Size f2.
|
||||
$data->profileimageurlsmall = $userpicture->get_url($PAGE)->out(false);
|
||||
// Store the message if we have it.
|
||||
$data->lastmessage = null;
|
||||
$data->messageid = null;
|
||||
if (isset($contact->smallmessage)) {
|
||||
$data->lastmessage = $contact->smallmessage;
|
||||
} else {
|
||||
$data->lastmessage = null;
|
||||
if (isset($contact->messageid)) {
|
||||
$data->messageid = $contact->messageid;
|
||||
}
|
||||
}
|
||||
// Check if the user is online.
|
||||
$data->isonline = $userfields->lastaccess >= $time;
|
||||
|
||||
@@ -61,6 +61,7 @@ class contact implements templatable, renderable {
|
||||
$contact->fullname = $this->contact->fullname;
|
||||
$contact->profileimageurl = $this->contact->profileimageurl;
|
||||
$contact->profileimageurlsmall = $this->contact->profileimageurlsmall;
|
||||
$contact->messageid = $this->contact->messageid;
|
||||
if ($this->contact->lastmessage) {
|
||||
$contact->lastmessage = shorten_text($this->contact->lastmessage, self::MAX_MSG_LENGTH);
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Contains class used to display message search results.
|
||||
*
|
||||
* @package core_message
|
||||
* @copyright 2016 Mark Nelson <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_message\output\messagearea;
|
||||
|
||||
use renderable;
|
||||
use templatable;
|
||||
|
||||
/**
|
||||
* Class used to display message search results.
|
||||
*
|
||||
* @package core_message
|
||||
* @copyright 2016 Mark Nelson <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class message_search_results implements templatable, renderable {
|
||||
|
||||
/**
|
||||
* The id of the user that the contacts belong to.
|
||||
*/
|
||||
protected $userid;
|
||||
|
||||
/**
|
||||
* The list of contacts with the.
|
||||
*/
|
||||
protected $contacts;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param int $userid The id of the user the search results belong to
|
||||
* @param \core_message\output\messagearea\contact[] $contacts
|
||||
*/
|
||||
public function __construct($userid, $contacts) {
|
||||
$this->userid = $userid;
|
||||
$this->contacts = $contacts;
|
||||
}
|
||||
|
||||
public function export_for_template(\renderer_base $output) {
|
||||
$data = new \stdClass();
|
||||
$data->userid = $this->userid;
|
||||
$data->contacts = array();
|
||||
foreach ($this->contacts as $contact) {
|
||||
$data->contacts[] = $contact->export_for_template($output);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Contains class used to display people search results.
|
||||
*
|
||||
* @package core_message
|
||||
* @copyright 2016 Mark Nelson <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace core_message\output\messagearea;
|
||||
|
||||
use renderable;
|
||||
use templatable;
|
||||
|
||||
/**
|
||||
* Class used to display people search results.
|
||||
*
|
||||
* @package core_message
|
||||
* @copyright 2016 Mark Nelson <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class people_search_results implements templatable, renderable {
|
||||
|
||||
/**
|
||||
* The list of contacts
|
||||
*/
|
||||
protected $contacts;
|
||||
|
||||
/**
|
||||
* The list of courses.
|
||||
*/
|
||||
protected $courses;
|
||||
|
||||
/**
|
||||
* The list of non-contacts.
|
||||
*/
|
||||
protected $noncontacts;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param \core_message\output\messagearea\contact[] $contacts
|
||||
* @param array $courses
|
||||
* @param \core_message\output\messagearea\contact[] $noncontacts
|
||||
*/
|
||||
public function __construct($contacts, $courses = array(), $noncontacts = array()) {
|
||||
$this->contacts = $contacts;
|
||||
$this->courses = $courses;
|
||||
$this->noncontacts = $noncontacts;
|
||||
}
|
||||
|
||||
public function export_for_template(\renderer_base $output) {
|
||||
// Set the defaults for the data we are going to export.
|
||||
$data = new \stdClass();
|
||||
$data->hascontacts = false;
|
||||
$data->contacts = array();
|
||||
$data->hascourses = false;
|
||||
$data->courses = array();
|
||||
$data->hasnoncontacts = false;
|
||||
$data->noncontacts = array();
|
||||
|
||||
// Check if there are any contacts.
|
||||
if (!empty($this->contacts)) {
|
||||
$data->hascontacts = true;
|
||||
foreach ($this->contacts as $contact) {
|
||||
$data->contacts[] = $contact->export_for_template($output);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if there are any courses.
|
||||
if (!empty($this->courses)) {
|
||||
$data->hascourses = true;
|
||||
$data->courses = $this->courses;
|
||||
}
|
||||
|
||||
// Check if there are any non-contacts.
|
||||
if (!empty($this->noncontacts)) {
|
||||
$data->hasnoncontacts = true;
|
||||
foreach ($this->noncontacts as $noncontact) {
|
||||
$data->noncontacts[] = $noncontact->export_for_template($output);
|
||||
}
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
@@ -420,6 +420,269 @@ class core_message_external extends external_api {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get messagearea search people parameters.
|
||||
*
|
||||
* @return external_function_parameters
|
||||
* @since 3.2
|
||||
*/
|
||||
public static function data_for_messagearea_search_people_in_course_parameters() {
|
||||
return new external_function_parameters(
|
||||
array(
|
||||
'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
|
||||
'courseid' => new external_value(PARAM_INT, 'The id of the course'),
|
||||
'search' => new external_value(PARAM_RAW, 'The string being searched'),
|
||||
'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
|
||||
'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get messagearea search people results.
|
||||
*
|
||||
* @param int $userid The id of the user who is performing the search
|
||||
* @param int $courseid The id of the course
|
||||
* @param string $search The string being searched
|
||||
* @param int $limitfrom
|
||||
* @param int $limitnum
|
||||
* @return stdClass
|
||||
* @throws moodle_exception
|
||||
* @since 3.2
|
||||
*/
|
||||
public static function data_for_messagearea_search_people_in_course($userid, $courseid, $search, $limitfrom = 0, $limitnum = 0) {
|
||||
global $CFG, $PAGE;
|
||||
|
||||
// Check if messaging is enabled.
|
||||
if (!$CFG->messaging) {
|
||||
throw new moodle_exception('disabled', 'message');
|
||||
}
|
||||
|
||||
$params = array(
|
||||
'userid' => $userid,
|
||||
'courseid' => $courseid,
|
||||
'search' => $search,
|
||||
'limitfrom' => $limitfrom,
|
||||
'limitnum' => $limitnum
|
||||
);
|
||||
self::validate_parameters(self::data_for_messagearea_search_people_in_course_parameters(), $params);
|
||||
|
||||
self::validate_context(context_user::instance($userid));
|
||||
|
||||
$search = \core_message\api::search_people_in_course($userid, $courseid, $search, $limitfrom, $limitnum);
|
||||
|
||||
$renderer = $PAGE->get_renderer('core_message');
|
||||
return $search->export_for_template($renderer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get messagearea search people returns.
|
||||
*
|
||||
* @return external_single_structure
|
||||
* @since 3.2
|
||||
*/
|
||||
public static function data_for_messagearea_search_people_in_course_returns() {
|
||||
return new external_single_structure(
|
||||
array(
|
||||
'hascontacts' => new external_value(PARAM_BOOL, 'Are there contacts?'),
|
||||
'contacts' => new external_multiple_structure(
|
||||
new external_single_structure(
|
||||
array(
|
||||
'userid' => new external_value(PARAM_INT, 'The user\'s id'),
|
||||
'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
|
||||
'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
|
||||
'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
|
||||
'lastmessage' => new external_value(PARAM_NOTAGS, 'The user\'s last message'),
|
||||
'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
|
||||
'isread' => new external_value(PARAM_BOOL, 'If the user has read the message'),
|
||||
)
|
||||
)
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get messagearea search people parameters.
|
||||
*
|
||||
* @return external_function_parameters
|
||||
* @since 3.2
|
||||
*/
|
||||
public static function data_for_messagearea_search_people_parameters() {
|
||||
return new external_function_parameters(
|
||||
array(
|
||||
'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
|
||||
'search' => new external_value(PARAM_RAW, 'The string being searched'),
|
||||
'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get messagearea search people results.
|
||||
*
|
||||
* @param int $userid The id of the user who is performing the search
|
||||
* @param string $search The string being searched
|
||||
* @param int $limitnum
|
||||
* @return stdClass
|
||||
* @throws moodle_exception
|
||||
* @since 3.2
|
||||
*/
|
||||
public static function data_for_messagearea_search_people($userid, $search, $limitnum = 0) {
|
||||
global $CFG, $PAGE;
|
||||
|
||||
// Check if messaging is enabled.
|
||||
if (!$CFG->messaging) {
|
||||
throw new moodle_exception('disabled', 'message');
|
||||
}
|
||||
|
||||
$params = array(
|
||||
'userid' => $userid,
|
||||
'search' => $search,
|
||||
'limitnum' => $limitnum
|
||||
);
|
||||
self::validate_parameters(self::data_for_messagearea_search_people_parameters(), $params);
|
||||
|
||||
self::validate_context(context_user::instance($userid));
|
||||
|
||||
$search = \core_message\api::search_people($userid, $search, $limitnum);
|
||||
|
||||
$renderer = $PAGE->get_renderer('core_message');
|
||||
return $search->export_for_template($renderer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get messagearea search people returns.
|
||||
*
|
||||
* @return external_single_structure
|
||||
* @since 3.2
|
||||
*/
|
||||
public static function data_for_messagearea_search_people_returns() {
|
||||
return new external_single_structure(
|
||||
array(
|
||||
'hascontacts' => new external_value(PARAM_BOOL, 'Are there contacts?'),
|
||||
'contacts' => new external_multiple_structure(
|
||||
new external_single_structure(
|
||||
array(
|
||||
'userid' => new external_value(PARAM_INT, 'The user\'s id'),
|
||||
'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
|
||||
'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
|
||||
'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
|
||||
'lastmessage' => new external_value(PARAM_NOTAGS, 'The user\'s last message'),
|
||||
'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
|
||||
'isread' => new external_value(PARAM_BOOL, 'If the user has read the message'),
|
||||
)
|
||||
)
|
||||
),
|
||||
'hascourses' => new external_value(PARAM_BOOL, 'Are there courses?'),
|
||||
'courses' => new external_multiple_structure(
|
||||
new external_single_structure(
|
||||
array(
|
||||
'id' => new external_value(PARAM_INT, 'The course id'),
|
||||
'shortname' => new external_value(PARAM_NOTAGS, 'The course shortname'),
|
||||
'fullname' => new external_value(PARAM_NOTAGS, 'The course fullname'),
|
||||
)
|
||||
)
|
||||
),
|
||||
'hasnoncontacts' => new external_value(PARAM_BOOL, 'Are there non-contacts?'),
|
||||
'noncontacts' => new external_multiple_structure(
|
||||
new external_single_structure(
|
||||
array(
|
||||
'userid' => new external_value(PARAM_INT, 'The user\'s id'),
|
||||
'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
|
||||
'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
|
||||
'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
|
||||
'lastmessage' => new external_value(PARAM_NOTAGS, 'The user\'s last message'),
|
||||
'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
|
||||
'isread' => new external_value(PARAM_BOOL, 'If the user has read the message'),
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get messagearea search messages parameters.
|
||||
*
|
||||
* @return external_function_parameters
|
||||
* @since 3.2
|
||||
*/
|
||||
public static function data_for_messagearea_search_messages_parameters() {
|
||||
return new external_function_parameters(
|
||||
array(
|
||||
'userid' => new external_value(PARAM_INT, 'The id of the user who is performing the search'),
|
||||
'search' => new external_value(PARAM_RAW, 'The string being searched'),
|
||||
'limitfrom' => new external_value(PARAM_INT, 'Limit from', VALUE_DEFAULT, 0),
|
||||
'limitnum' => new external_value(PARAM_INT, 'Limit number', VALUE_DEFAULT, 0)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get messagearea search messages results.
|
||||
*
|
||||
* @param int $userid The id of the user who is performing the search
|
||||
* @param string $search The string being searched
|
||||
* @param int $limitfrom
|
||||
* @param int $limitnum
|
||||
* @return stdClass
|
||||
* @throws moodle_exception
|
||||
* @since 3.2
|
||||
*/
|
||||
public static function data_for_messagearea_search_messages($userid, $search, $limitfrom = 0, $limitnum = 0) {
|
||||
global $CFG, $PAGE;
|
||||
|
||||
// Check if messaging is enabled.
|
||||
if (!$CFG->messaging) {
|
||||
throw new moodle_exception('disabled', 'message');
|
||||
}
|
||||
|
||||
$params = array(
|
||||
'userid' => $userid,
|
||||
'search' => $search,
|
||||
'limitfrom' => $limitfrom,
|
||||
'limitnum' => $limitnum
|
||||
|
||||
);
|
||||
self::validate_parameters(self::data_for_messagearea_search_messages_parameters(), $params);
|
||||
|
||||
self::validate_context(context_user::instance($userid));
|
||||
|
||||
$search = \core_message\api::search_messages($userid, $search, $limitfrom, $limitnum);
|
||||
|
||||
$renderer = $PAGE->get_renderer('core_message');
|
||||
return $search->export_for_template($renderer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get messagearea search messages returns.
|
||||
*
|
||||
* @return external_single_structure
|
||||
* @since 3.2
|
||||
*/
|
||||
public static function data_for_messagearea_search_messages_returns() {
|
||||
return new external_single_structure(
|
||||
array(
|
||||
'userid' => new external_value(PARAM_INT, 'The id of the user who we are viewing conversations for'),
|
||||
'contacts' => new external_multiple_structure(
|
||||
new external_single_structure(
|
||||
array(
|
||||
'userid' => new external_value(PARAM_INT, 'The user\'s id'),
|
||||
'fullname' => new external_value(PARAM_NOTAGS, 'The user\'s name'),
|
||||
'profileimageurl' => new external_value(PARAM_URL, 'User picture URL'),
|
||||
'profileimageurlsmall' => new external_value(PARAM_URL, 'Small user picture URL'),
|
||||
'lastmessage' => new external_value(PARAM_NOTAGS, 'The user\'s last message'),
|
||||
'messageid' => new external_value(PARAM_INT, 'The unique search message id'),
|
||||
'isonline' => new external_value(PARAM_BOOL, 'The user\'s online status'),
|
||||
'isread' => new external_value(PARAM_BOOL, 'If the user has read the message'),
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The messagearea conversations parameters.
|
||||
*
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<div class="row-fluid contact {{#selected}}selected{{/selected}}" data-action="{{#lastmessage}}view-contact-msg{{/lastmessage}}{{^lastmessage}}view-contact-profile{{/lastmessage}}" data-userid="{{userid}}" data-region="contact" tabindex="0">
|
||||
<div class="row-fluid contact {{#selected}}selected{{/selected}}"
|
||||
data-action="{{#lastmessage}}view-contact-msg{{/lastmessage}}{{^lastmessage}}view-contact-profile{{/lastmessage}}"
|
||||
data-userid="{{userid}}" data-messageid="{{#messageid}}{{.}}{{isread}}{{/messageid}}" data-region="contact" tabindex="0">
|
||||
<div class="span3 picture">
|
||||
<img src="{{profileimageurl}}" alt="" />
|
||||
</div>
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
<div class="searcharea" data-region="search-area">
|
||||
<div class="searchtextarea" data-region="search-text-area">
|
||||
<form>
|
||||
<label class="accesshide" for="filter{{uniqid}}">{{#str}}search{{/str}}</label>
|
||||
<input data-region="search-box" type="text" id="filter{{uniqid}}" placeholder="{{#str}}search{{/str}}" value="{{search}}">
|
||||
<label class="accesshide" for="searchtext">{{#str}}search{{/str}}</label>
|
||||
<input data-region="search-box" type="text" id="searchtext" placeholder="{{#str}}searchmessages, message{{/str}}">
|
||||
</form>
|
||||
<div data-region="search-filter-area" class="searchfilterarea" style="display:none">
|
||||
<div data-region="search-filter" class="searchfilter"></div>
|
||||
<div data-action="search-filter-delete" class="searchfilterdelete">{{#pix}}t/delete{{/pix}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="contacts" data-region="contacts" data-region-content="conversations" role="tabpanel" id="conversations-tab-panel">
|
||||
{{> core_message/message_area_contacts }}
|
||||
</div>
|
||||
{{! Hidden div to load the other tabs items in via JS when appropriate. }}
|
||||
{{! Hidden divs to load the other tab and search panels via JS when appropriate. }}
|
||||
<div class="contacts" data-region="contacts" data-region-content="contacts" style="display:none;" role="tabpanel" id="contacts-tab-panel"></div>
|
||||
<div class="contacts searcharea" data-region="search-results-area" style="display:none;"></div>
|
||||
<div class="row-fluid tabs">
|
||||
<div class="span6 tab tabconversations selected" data-action="conversations-view" role="tab" aria-controls="conversations-tab-panel" aria-selected="true" tabindex="0">
|
||||
<div class="tabimage">{{#pix}}t/message, moodle{{/pix}}</div>
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
{{#hascontacts}}
|
||||
{{#contacts}}
|
||||
{{> core_message/message_area_contact }}
|
||||
{{/contacts}}
|
||||
{{/hascontacts}}
|
||||
{{#hascourses}}
|
||||
<div class="heading">{{#str}}courses{{/str}}</div>
|
||||
{{#courses}}
|
||||
<div class="course" data-action="search-people-in-course" data-courseid="{{id}}">
|
||||
{{fullname}}
|
||||
</div>
|
||||
{{/courses}}
|
||||
{{/hascourses}}
|
||||
{{#hasnoncontacts}}
|
||||
<div class="heading">{{#str}}noncontacts, message{{/str}}</div>
|
||||
{{#noncontacts}}
|
||||
{{> core_message/message_area_contact }}
|
||||
{{/noncontacts}}
|
||||
{{/hasnoncontacts}}
|
||||
@@ -51,7 +51,18 @@
|
||||
border-right: 1px solid #e3e3e3;
|
||||
height: 600px;
|
||||
|
||||
.searcharea {
|
||||
&.searchfilter {
|
||||
|
||||
.searchtextarea {
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.searcharea {
|
||||
height: 470px;
|
||||
}
|
||||
}
|
||||
|
||||
.searchtextarea {
|
||||
padding: 5px;
|
||||
text-align: center;
|
||||
height: 50px;
|
||||
@@ -85,6 +96,42 @@
|
||||
transition: background-color linear 0.2s;
|
||||
}
|
||||
}
|
||||
|
||||
.searchfilterarea {
|
||||
line-height: 20px;
|
||||
|
||||
.searchfilter {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.searchfilterdelete {
|
||||
float: left;
|
||||
margin-left: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.searcharea {
|
||||
|
||||
.heading {
|
||||
text-align: center;
|
||||
border-top: 1px solid black;
|
||||
border-bottom: 1px solid black;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.course {
|
||||
text-align: center;
|
||||
|
||||
&:hover {
|
||||
background-color: #4f94cd;
|
||||
color: #fff;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.contacts {
|
||||
|
||||
@@ -5795,7 +5795,13 @@ a.ygtvspacer:hover {
|
||||
border-right: 1px solid #e3e3e3;
|
||||
height: 600px;
|
||||
}
|
||||
.messaging-area-container .messaging-area .contacts-area .searcharea {
|
||||
.messaging-area-container .messaging-area .contacts-area.searchfilter .searchtextarea {
|
||||
height: 80px;
|
||||
}
|
||||
.messaging-area-container .messaging-area .contacts-area.searchfilter .searcharea {
|
||||
height: 470px;
|
||||
}
|
||||
.messaging-area-container .messaging-area .contacts-area .searchtextarea {
|
||||
padding: 5px;
|
||||
text-align: center;
|
||||
height: 50px;
|
||||
@@ -5804,7 +5810,7 @@ a.ygtvspacer:hover {
|
||||
background-color: #fff;
|
||||
transition: background-color linear 0.2s;
|
||||
}
|
||||
.messaging-area-container .messaging-area .contacts-area .searcharea input {
|
||||
.messaging-area-container .messaging-area .contacts-area .searchtextarea input {
|
||||
background-color: #f5f5f5;
|
||||
border: 0;
|
||||
width: 90%;
|
||||
@@ -5813,19 +5819,46 @@ a.ygtvspacer:hover {
|
||||
box-shadow: none;
|
||||
transition: background-color linear 0.2s;
|
||||
}
|
||||
.messaging-area-container .messaging-area .contacts-area .searcharea input:focus {
|
||||
.messaging-area-container .messaging-area .contacts-area .searchtextarea input:focus {
|
||||
-webkit-box-shadow: none;
|
||||
-moz-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
.messaging-area-container .messaging-area .contacts-area .searcharea.searching {
|
||||
.messaging-area-container .messaging-area .contacts-area .searchtextarea.searching {
|
||||
background-color: #f5f5f5;
|
||||
transition: background-color linear 0.2s;
|
||||
}
|
||||
.messaging-area-container .messaging-area .contacts-area .searcharea.searching input {
|
||||
.messaging-area-container .messaging-area .contacts-area .searchtextarea.searching input {
|
||||
background-color: #fff;
|
||||
transition: background-color linear 0.2s;
|
||||
}
|
||||
.messaging-area-container .messaging-area .contacts-area .searchtextarea .searchfilterarea {
|
||||
line-height: 20px;
|
||||
}
|
||||
.messaging-area-container .messaging-area .contacts-area .searchtextarea .searchfilterarea .searchfilter {
|
||||
float: left;
|
||||
}
|
||||
.messaging-area-container .messaging-area .contacts-area .searchtextarea .searchfilterarea .searchfilterdelete {
|
||||
float: left;
|
||||
margin-left: 5px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.messaging-area-container .messaging-area .contacts-area .searcharea .heading {
|
||||
text-align: center;
|
||||
border-top: 1px solid black;
|
||||
border-bottom: 1px solid black;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.messaging-area-container .messaging-area .contacts-area .searcharea .course {
|
||||
text-align: center;
|
||||
}
|
||||
.messaging-area-container .messaging-area .contacts-area .searcharea .course:hover {
|
||||
background-color: #4f94cd;
|
||||
color: #fff;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
.messaging-area-container .messaging-area .contacts-area .contacts {
|
||||
height: 500px;
|
||||
overflow-y: scroll;
|
||||
|
||||
Reference in New Issue
Block a user