message/amd/src/message_drawer_view_contacts.js

  1. // This file is part of Moodle - http://moodle.org/
  2. //
  3. // Moodle is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU General Public License as published by
  5. // the Free Software Foundation, either version 3 of the License, or
  6. // (at your option) any later version.
  7. //
  8. // Moodle is distributed in the hope that it will be useful,
  9. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. // GNU General Public License for more details.
  12. //
  13. // You should have received a copy of the GNU General Public License
  14. // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
  15. /**
  16. * Controls the contacts page of the message drawer.
  17. *
  18. * @module core_message/message_drawer_view_contacts
  19. * @copyright 2018 Ryan Wyllie <ryan@moodle.com>
  20. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  21. */
  22. define(
  23. [
  24. 'jquery',
  25. 'core/pubsub',
  26. 'core/str',
  27. 'core_message/message_drawer_events',
  28. 'core_message/message_drawer_view_contacts_section_contacts',
  29. 'core_message/message_drawer_view_contacts_section_requests'
  30. ],
  31. function(
  32. $,
  33. PubSub,
  34. Str,
  35. MessageDrawerEvents,
  36. ContactsSection,
  37. RequestsSection
  38. ) {
  39. var SELECTORS = {
  40. ACTION_SHOW_CONTACTS_SECTION: '[data-action="show-contacts-section"]',
  41. ACTION_SHOW_REQUESTS_SECTION: '[data-action="show-requests-section"]',
  42. CONTACT_REQUEST_COUNT: '[data-region="contact-request-count"]',
  43. CONTACTS_SECTION_CONTAINER: '[data-section="contacts"]',
  44. REQUESTS_SECTION_CONTAINER: '[data-section="requests"]',
  45. };
  46. /**
  47. * Get the container element for the contacts section.
  48. *
  49. * @param {Object} body Contacts page body element.
  50. * @return {Object}
  51. */
  52. var getContactsSectionContainer = function(body) {
  53. return body.find(SELECTORS.CONTACTS_SECTION_CONTAINER);
  54. };
  55. /**
  56. * Get the container element for the requests section.
  57. *
  58. * @param {Object} body Contacts page body element.
  59. * @return {Object}
  60. */
  61. var getRequestsSectionContainer = function(body) {
  62. return body.find(SELECTORS.REQUESTS_SECTION_CONTAINER);
  63. };
  64. /**
  65. * Get the element that triggers showing the contacts section.
  66. *
  67. * @param {Object} body Contacts page body element.
  68. * @return {Object}
  69. */
  70. var getShowContactsAction = function(body) {
  71. return body.find(SELECTORS.ACTION_SHOW_CONTACTS_SECTION);
  72. };
  73. /**
  74. * Get the element that triggers showing the requests section.
  75. *
  76. * @param {Object} body Contacts page body element.
  77. * @return {Object}
  78. */
  79. var getShowRequestsAction = function(body) {
  80. return body.find(SELECTORS.ACTION_SHOW_REQUESTS_SECTION);
  81. };
  82. /**
  83. * Check if the given section is visible.
  84. *
  85. * @param {Object} sectionRoot The root element for the section
  86. * @return {Bool}
  87. */
  88. var isSectionVisible = function(sectionRoot) {
  89. return sectionRoot.hasClass('active');
  90. };
  91. /**
  92. * Decrement the contact request count. If the count is zero or below then
  93. * hide the count.
  94. *
  95. * @param {Object} body Conversation body container element.
  96. * @return {Function} A function to handle decrementing the count.
  97. */
  98. var decrementContactRequestCount = function(body) {
  99. return function() {
  100. var countContainer = body.find(SELECTORS.CONTACT_REQUEST_COUNT);
  101. var count = parseInt(countContainer.text(), 10);
  102. count = isNaN(count) ? 0 : count - 1;
  103. if (count <= 0) {
  104. countContainer.addClass('hidden');
  105. } else {
  106. countContainer.text(count);
  107. }
  108. };
  109. };
  110. /**
  111. * Listen to and handle events for contacts.
  112. *
  113. * @param {Object} body Contacts body container element.
  114. */
  115. var registerEventListeners = function(body) {
  116. var contactsSection = getContactsSectionContainer(body);
  117. var requestsSection = getRequestsSectionContainer(body);
  118. var showContactsAction = getShowContactsAction(body);
  119. var showRequestsAction = getShowRequestsAction(body);
  120. showContactsAction.on('show.bs.tab', function() {
  121. ContactsSection.show(contactsSection);
  122. });
  123. showRequestsAction.on('show.bs.tab', function() {
  124. RequestsSection.show(requestsSection);
  125. });
  126. PubSub.subscribe(MessageDrawerEvents.CONTACT_REQUEST_ACCEPTED, decrementContactRequestCount(body));
  127. PubSub.subscribe(MessageDrawerEvents.CONTACT_REQUEST_DECLINED, decrementContactRequestCount(body));
  128. };
  129. /**
  130. * Setup the contact page.
  131. *
  132. * @param {string} namespace The route namespace.
  133. * @param {Object} header Contacts header container element.
  134. * @param {Object} body Contacts body container element.
  135. * @param {Object} footer Contacts footer container element.
  136. * @param {String|null} tab Tab to show, either 'requests' or 'contacts', if any.
  137. * @return {Object} jQuery promise
  138. */
  139. var show = function(namespace, header, body, footer, tab) {
  140. body = $(body);
  141. if (!body.attr('data-contacts-init')) {
  142. registerEventListeners(body);
  143. body.attr('data-contacts-init', true);
  144. }
  145. var contactsSection = getContactsSectionContainer(body);
  146. var requestsSection = getRequestsSectionContainer(body);
  147. if (tab) {
  148. var showContactsAction = getShowContactsAction(body);
  149. var showRequestsAction = getShowRequestsAction(body);
  150. // Unfortunately we need to hardcode the class changes here rather than trigger
  151. // the bootstrap tab functionality because the bootstrap JS doesn't appear to be
  152. // loaded by this point which means the tab plugin isn't added and the event listeners
  153. // haven't been set up so we can't just trigger a click either.
  154. if (tab == 'requests') {
  155. showContactsAction.removeClass('active');
  156. contactsSection.removeClass('show active');
  157. showRequestsAction.addClass('active');
  158. requestsSection.addClass('show active');
  159. } else {
  160. showRequestsAction.removeClass('active');
  161. requestsSection.removeClass('show active');
  162. showContactsAction.addClass('active');
  163. contactsSection.addClass('show active');
  164. }
  165. }
  166. if (isSectionVisible(contactsSection)) {
  167. ContactsSection.show(contactsSection);
  168. } else {
  169. RequestsSection.show(requestsSection);
  170. }
  171. return $.Deferred().resolve().promise();
  172. };
  173. /**
  174. * String describing this page used for aria-labels.
  175. *
  176. * @return {Object} jQuery promise
  177. */
  178. var description = function() {
  179. return Str.get_string('messagedrawerviewcontacts', 'core_message');
  180. };
  181. return {
  182. show: show,
  183. description: description
  184. };
  185. });