reportbuilder/amd/src/schedules.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. * Report builder audiences
  17. *
  18. * @module core_reportbuilder/schedules
  19. * @copyright 2021 Paul Holden <paulh@moodle.com>
  20. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  21. */
  22. "use strict";
  23. import {dispatchEvent} from 'core/event_dispatcher';
  24. import 'core/inplace_editable';
  25. import Notification from 'core/notification';
  26. import Pending from 'core/pending';
  27. import {prefetchStrings} from 'core/prefetch';
  28. import {getString} from 'core/str';
  29. import {add as addToast} from 'core/toast';
  30. import * as reportEvents from 'core_reportbuilder/local/events';
  31. import * as reportSelectors from 'core_reportbuilder/local/selectors';
  32. import {createScheduleModal} from 'core_reportbuilder/local/repository/modals';
  33. import {deleteSchedule, sendSchedule, toggleSchedule} from 'core_reportbuilder/local/repository/schedules';
  34. let initialized = false;
  35. /**
  36. * Initialise schedules tab
  37. *
  38. * @param {Number} reportId
  39. */
  40. export const init = reportId => {
  41. prefetchStrings('core_reportbuilder', [
  42. 'deleteschedule',
  43. 'deletescheduleconfirm',
  44. 'disableschedule',
  45. 'editscheduledetails',
  46. 'enableschedule',
  47. 'newschedule',
  48. 'schedulecreated',
  49. 'scheduledeleted',
  50. 'schedulesent',
  51. 'scheduleupdated',
  52. 'sendschedule',
  53. 'sendscheduleconfirm',
  54. ]);
  55. prefetchStrings('core', [
  56. 'confirm',
  57. 'delete',
  58. ]);
  59. if (initialized) {
  60. // We already added the event listeners (can be called multiple times by mustache template).
  61. return;
  62. }
  63. document.addEventListener('click', event => {
  64. // Create schedule.
  65. const scheduleCreate = event.target.closest(reportSelectors.actions.scheduleCreate);
  66. if (scheduleCreate) {
  67. event.preventDefault();
  68. const scheduleModal = createScheduleModal(event.target, getString('newschedule', 'core_reportbuilder'), reportId);
  69. scheduleModal.addEventListener(scheduleModal.events.FORM_SUBMITTED, () => {
  70. getString('schedulecreated', 'core_reportbuilder')
  71. .then(addToast)
  72. .then(() => {
  73. const reportElement = document.querySelector(reportSelectors.regions.report);
  74. dispatchEvent(reportEvents.tableReload, {}, reportElement);
  75. return;
  76. })
  77. .catch(Notification.exception);
  78. });
  79. scheduleModal.show();
  80. }
  81. // Toggle schedule.
  82. const scheduleToggle = event.target.closest(reportSelectors.actions.scheduleToggle);
  83. if (scheduleToggle) {
  84. const pendingPromise = new Pending('core_reportbuilder/schedules:toggle');
  85. const scheduleStateToggle = +!Number(scheduleToggle.dataset.state);
  86. toggleSchedule(reportId, scheduleToggle.dataset.id, scheduleStateToggle)
  87. .then(() => {
  88. const tableRow = scheduleToggle.closest('tr');
  89. tableRow.classList.toggle('text-muted');
  90. scheduleToggle.dataset.state = scheduleStateToggle;
  91. const stringKey = scheduleStateToggle ? 'disableschedule' : 'enableschedule';
  92. return getString(stringKey, 'core_reportbuilder');
  93. })
  94. .then(toggleLabel => {
  95. const labelContainer = scheduleToggle.parentElement.querySelector(`label[for="${scheduleToggle.id}"] > span`);
  96. labelContainer.innerHTML = toggleLabel;
  97. return pendingPromise.resolve();
  98. })
  99. .catch(Notification.exception);
  100. }
  101. // Edit schedule.
  102. const scheduleEdit = event.target.closest(reportSelectors.actions.scheduleEdit);
  103. if (scheduleEdit) {
  104. event.preventDefault();
  105. // Use triggerElement to return focus to the action menu toggle.
  106. const triggerElement = scheduleEdit.closest('.dropdown').querySelector('.dropdown-toggle');
  107. const scheduleModal = createScheduleModal(triggerElement, getString('editscheduledetails', 'core_reportbuilder'),
  108. reportId, scheduleEdit.dataset.scheduleId);
  109. scheduleModal.addEventListener(scheduleModal.events.FORM_SUBMITTED, () => {
  110. getString('scheduleupdated', 'core_reportbuilder')
  111. .then(addToast)
  112. .then(() => {
  113. const reportElement = scheduleEdit.closest(reportSelectors.regions.report);
  114. dispatchEvent(reportEvents.tableReload, {}, reportElement);
  115. return;
  116. })
  117. .catch(Notification.exception);
  118. });
  119. scheduleModal.show();
  120. }
  121. // Send schedule.
  122. const scheduleSend = event.target.closest(reportSelectors.actions.scheduleSend);
  123. if (scheduleSend) {
  124. event.preventDefault();
  125. // Use triggerElement to return focus to the action menu toggle.
  126. const triggerElement = scheduleSend.closest('.dropdown').querySelector('.dropdown-toggle');
  127. Notification.saveCancelPromise(
  128. getString('sendschedule', 'core_reportbuilder'),
  129. getString('sendscheduleconfirm', 'core_reportbuilder', scheduleSend.dataset.scheduleName),
  130. getString('confirm', 'core'),
  131. {triggerElement}
  132. ).then(() => {
  133. const pendingPromise = new Pending('core_reportbuilder/schedules:send');
  134. return sendSchedule(reportId, scheduleSend.dataset.scheduleId)
  135. .then(addToast(getString('schedulesent', 'core_reportbuilder')))
  136. .then(() => pendingPromise.resolve())
  137. .catch(Notification.exception);
  138. }).catch(() => {
  139. return;
  140. });
  141. }
  142. // Delete schedule.
  143. const scheduleDelete = event.target.closest(reportSelectors.actions.scheduleDelete);
  144. if (scheduleDelete) {
  145. event.preventDefault();
  146. // Use triggerElement to return focus to the action menu toggle.
  147. const triggerElement = scheduleDelete.closest('.dropdown').querySelector('.dropdown-toggle');
  148. Notification.saveCancelPromise(
  149. getString('deleteschedule', 'core_reportbuilder'),
  150. getString('deletescheduleconfirm', 'core_reportbuilder', scheduleDelete.dataset.scheduleName),
  151. getString('delete', 'core'),
  152. {triggerElement}
  153. ).then(() => {
  154. const pendingPromise = new Pending('core_reportbuilder/schedules:delete');
  155. return deleteSchedule(reportId, scheduleDelete.dataset.scheduleId)
  156. .then(addToast(getString('scheduledeleted', 'core_reportbuilder')))
  157. .then(() => {
  158. const reportElement = scheduleDelete.closest(reportSelectors.regions.report);
  159. dispatchEvent(reportEvents.tableReload, {preservePagination: true}, reportElement);
  160. return pendingPromise.resolve();
  161. })
  162. .catch(Notification.exception);
  163. }).catch(() => {
  164. return;
  165. });
  166. }
  167. });
  168. initialized = true;
  169. };