f9b62a670d4bfac45ace06eba9c4fd1d98366a85
[moodle.git] / user / amd / src / participants.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/>.
16 /**
17  * Some UI stuff for participants page.
18  * This is also used by the report/participants/index.php because it has the same functionality.
19  *
20  * @module     core_user/participants
21  * @package    core_user
22  * @copyright  2017 Damyon Wiese
23  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24  */
26 import * as DynamicTable from 'core_table/dynamic';
27 import * as Str from 'core/str';
28 import CheckboxToggleAll from 'core/checkbox-toggleall';
29 import CustomEvents from 'core/custom_interaction_events';
30 import DynamicTableSelectors from 'core_table/local/dynamic/selectors';
31 import ModalEvents from 'core/modal_events';
32 import Notification from 'core/notification';
33 import jQuery from 'jquery';
34 import {showAddNote, showSendMessage} from 'core_user/local/participants/bulkactions';
36 const Selectors = {
37     bulkActionSelect: "#formactionid",
38     bulkUserSelectedCheckBoxes: "input[data-togglegroup='participants-table']:checked",
39     checkCountButton: "#checkall",
40     showCountText: '[data-region="participant-count"]',
41     showCountToggle: '[data-action="showcount"]',
42     stateHelpIcon: '[data-region="state-help-icon"]',
43     tableForm: uniqueId => `form[data-table-unique-id="${uniqueId}"]`,
44 };
46 export const init = ({
47     uniqueid,
48     noteStateNames = {},
49 }) => {
50     const root = document.querySelector(Selectors.tableForm(uniqueid));
51     const getTableFromUniqueId = uniqueId => root.querySelector(DynamicTableSelectors.main.fromRegionId(uniqueId));
53     /**
54      * Private method.
55      *
56      * @method registerEventListeners
57      * @private
58      */
59     const registerEventListeners = () => {
60         CustomEvents.define(Selectors.bulkActionSelect, [CustomEvents.events.accessibleChange]);
61         jQuery(Selectors.bulkActionSelect).on(CustomEvents.events.accessibleChange, e => {
62             const action = e.target.value;
63             const tableRoot = getTableFromUniqueId(uniqueid);
64             const checkboxes = tableRoot.querySelectorAll(Selectors.bulkUserSelectedCheckBoxes);
66             if (action.indexOf('#') !== -1) {
67                 e.preventDefault();
69                 const ids = [];
70                 checkboxes.forEach(checkbox => {
71                     ids.push(checkbox.getAttribute('name').replace('user', ''));
72                 });
74                 let bulkAction;
75                 if (action === '#messageselect') {
76                     bulkAction = showSendMessage(ids);
77                 } else if (action === '#addgroupnote') {
78                     bulkAction = showAddNote(
79                         root.dataset.courseId,
80                         ids,
81                         noteStateNames,
82                         root.querySelector(Selectors.stateHelpIcon)
83                     );
84                 }
86                 if (bulkAction) {
87                     bulkAction
88                     .then(modal => {
89                         modal.getRoot().on(ModalEvents.hidden, () => {
90                             // Focus on the action select when the dialog is closed.
91                             const bulkActionSelector = root.querySelector(Selectors.bulkActionSelect);
92                             bulkActionSelector.focus();
93                         });
95                         return modal;
96                     })
97                     .catch(Notification.exception);
98                 }
99             } else if (action !== '' && checkboxes.length) {
100                 e.target.form.submit();
101             }
103             resetBulkAction(e.target);
104         });
106         root.addEventListener('click', e => {
107             // Handle clicking of the "Show [all|count]" and "Select all" actions.
108             const showCountLink = root.querySelector(Selectors.showCountToggle);
109             const checkCountButton = root.querySelector(Selectors.checkCountButton);
111             const showCountLinkClicked = showCountLink && showCountLink.contains(e.target);
112             const checkCountButtonClicked = checkCountButton && checkCountButton.contains(e.target);
114             if (showCountLinkClicked || checkCountButtonClicked) {
115                 e.preventDefault();
117                 const tableRoot = getTableFromUniqueId(uniqueid);
119                 DynamicTable.setPageSize(tableRoot, showCountLink.dataset.targetPageSize)
120                 .then(tableRoot => {
121                     // Always update the toggle state.
122                     // This ensures that the bulk actions are disabled after changing the page size.
123                     CheckboxToggleAll.setGroupState(tableRoot, 'participants-table', checkCountButtonClicked);
125                     return tableRoot;
126                 })
127                 .catch(Notification.exception);
128             }
129         });
131         // When the content is refreshed, update the row counts in various places.
132         root.addEventListener(DynamicTable.Events.tableContentRefreshed, e => {
133             const showCountLink = root.querySelector(Selectors.showCountToggle);
134             const checkCountButton = root.querySelector(Selectors.checkCountButton);
136             const tableRoot = e.target;
138             const defaultPageSize = parseInt(root.dataset.tableDefaultPerPage, 10);
139             const currentPageSize = parseInt(tableRoot.dataset.tablePageSize, 10);
140             const totalRowCount = parseInt(tableRoot.dataset.tableTotalRows, 10);
142             CheckboxToggleAll.updateSlavesFromMasterState(tableRoot, 'participants-table');
144             const pageCountStrings = [
145                 {
146                     key: 'countparticipantsfound',
147                     component: 'core_user',
148                     param: totalRowCount,
149                 },
150             ];
153             if (totalRowCount <= defaultPageSize) {
154                 // There are fewer than the default page count numbers of rows.
155                 showCountLink.classList.add('hidden');
157                 if (checkCountButton) {
158                     checkCountButton.classList.add('hidden');
159                 }
160             } else if (totalRowCount <= currentPageSize) {
161                 // The are fewer than the current page size.
162                 pageCountStrings.push({
163                     key: 'showperpage',
164                     component: 'core',
165                     param: defaultPageSize,
166                 });
168                 pageCountStrings.push({
169                     key: 'selectalluserswithcount',
170                     component: 'core',
171                     param: defaultPageSize,
172                 });
174                 // Show the 'Show [x]' link.
175                 showCountLink.classList.remove('hidden');
176                 showCountLink.dataset.targetPageSize = defaultPageSize;
178                 if (checkCountButton) {
179                     // The 'Check all [x]' button is only visible when there are values to set.
180                     checkCountButton.classList.add('hidden');
181                 }
182             } else {
183                 pageCountStrings.push({
184                     key: 'showall',
185                     component: 'core',
186                     param: totalRowCount,
187                 });
189                 pageCountStrings.push({
190                     key: 'selectalluserswithcount',
191                     component: 'core',
192                     param: totalRowCount,
193                 });
195                 // Show both the 'Show [x]' link, and the 'Check all [x]' button.
196                 showCountLink.classList.remove('hidden');
197                 showCountLink.dataset.targetPageSize = totalRowCount;
199                 if (checkCountButton) {
200                     checkCountButton.classList.remove('hidden');
201                 }
202             }
204             Str.get_strings(pageCountStrings)
205             .then(([showingParticipantCountString, showCountString, selectCountString]) => {
206                 const showingParticipantCount = root.querySelector(Selectors.showCountText);
207                 showingParticipantCount.innerHTML = showingParticipantCountString;
209                 if (showCountString) {
210                     showCountLink.innerHTML = showCountString;
211                 }
213                 if (selectCountString && checkCountButton) {
214                     checkCountButton.value = selectCountString;
215                 }
217                 return;
218             })
219             .catch(Notification.exception);
220         });
221     };
223     const resetBulkAction = bulkActionSelect => {
224         bulkActionSelect.value = '';
225     };
227     registerEventListeners();
228 };