// 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/>.
/**
* Add policy consent modal to the page
*
* @module tool_policy/acceptmodal
* @copyright 2018 Marina Glancy
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define([
'jquery',
'core/str',
'core/modal_factory',
'core/modal_events',
'core/notification',
'core/fragment',
'core/ajax',
'core_form/changechecker',
], function(
$,
Str,
ModalFactory,
ModalEvents,
Notification,
Fragment,
Ajax,
FormChangeChecker
) {
"use strict";
/**
* Constructor
*
* @param {int} contextid
*
* Each call to init gets it's own instance of this class.
*/
var AcceptOnBehalf = function(contextid) {
this.contextid = contextid;
this.init();
};
/**
* @var {Modal} modal
* @private
*/
AcceptOnBehalf.prototype.modal = null;
/**
* @var {int} contextid
* @private
*/
AcceptOnBehalf.prototype.contextid = -1;
/**
* @var {object} currentTrigger The triggered HTML jQuery object
* @private
*/
AcceptOnBehalf.prototype.currentTrigger = null;
/**
* @var {object} triggers The trigger selectors
* @private
*/
AcceptOnBehalf.prototype.triggers = {
SINGLE: 'a[data-action=acceptmodal]',
BULK: 'input[data-action=acceptmodal]'
};
/**
* Initialise the class.
*
* @private
*/
AcceptOnBehalf.prototype.init = function() {
// Initialise for links accepting policies for individual users.
$(this.triggers.SINGLE).on('click', function(e) {
e.preventDefault();
this.currentTrigger = $(e.currentTarget);
var href = $(e.currentTarget).attr('href'),
formData = href.slice(href.indexOf('?') + 1);
this.showFormModal(formData);
}.bind(this));
// Initialise for multiple users acceptance form.
$(this.triggers.BULK).on('click', function(e) {
e.preventDefault();
this.currentTrigger = $(e.currentTarget);
var form = $(e.currentTarget).closest('form');
if (form.find('input[type=checkbox][name="userids[]"]:checked').length) {
var formData = form.serialize();
this.showFormModal(formData);
} else {
Str.get_strings([
{key: 'notice'},
{key: 'selectusersforconsent', component: 'tool_policy'},
{key: 'ok'}
]).then(function(strings) {
Notification.alert(strings[0], strings[1], strings[2]);
return;
}).fail(Notification.exception);
}
}.bind(this));
};
/**
* Show modal with a form
*
* @param {String} formData
*/
AcceptOnBehalf.prototype.showFormModal = function(formData) {
var action;
var params = formData.split('&');
for (var i = 0; i < params.length; i++) {
var pair = params[i].split('=');
if (pair[0] == 'action') {
action = pair[1];
}
}
// Fetch the title string.
Str.get_strings([
{key: 'statusformtitleaccept', component: 'tool_policy'},
{key: 'iagreetothepolicy', component: 'tool_policy'},
{key: 'statusformtitlerevoke', component: 'tool_policy'},
{key: 'irevokethepolicy', component: 'tool_policy'},
{key: 'statusformtitledecline', component: 'tool_policy'},
{key: 'declinethepolicy', component: 'tool_policy'}
]).then(function(strings) {
var title;
var saveText;
if (action == 'accept') {
title = strings[0];
saveText = strings[1];
} else if (action == 'revoke') {
title = strings[2];
saveText = strings[3];
} else if (action == 'decline') {
title = strings[4];
saveText = strings[5];
}
// Create the modal.
return ModalFactory.create({
type: ModalFactory.types.SAVE_CANCEL,
title: title,
body: ''
}).done(function(modal) {
this.modal = modal;
this.setupFormModal(formData, saveText);
}.bind(this));
}.bind(this))
.catch(Notification.exception);
};
/**
* Setup form inside a modal
*
* @param {String} formData
* @param {String} saveText
*/
AcceptOnBehalf.prototype.setupFormModal = function(formData, saveText) {
var modal = this.modal;
modal.setLarge();
modal.setSaveButtonText(saveText);
// We want to reset the form every time it is opened.
modal.getRoot().on(ModalEvents.hidden, this.destroy.bind(this));
modal.setBody(this.getBody(formData));
// We catch the modal save event, and use it to submit the form inside the modal.
// Triggering a form submission will give JS validation scripts a chance to check for errors.
modal.getRoot().on(ModalEvents.save, this.submitForm.bind(this));
// We also catch the form submit event and use it to submit the form with ajax.
modal.getRoot().on('submit', 'form', this.submitFormAjax.bind(this));
modal.show();
};
/**
* Load the body of the modal (contains the form)
*
* @method getBody
* @private
* @param {String} formData
* @return {Promise}
*/
AcceptOnBehalf.prototype.getBody = function(formData) {
if (typeof formData === "undefined") {
formData = {};
}
// Get the content of the modal.
var params = {jsonformdata: JSON.stringify(formData)};
return Fragment.loadFragment('tool_policy', 'accept_on_behalf', this.contextid, params);
};
/**
* Submit the form inside the modal via AJAX request
*
* @method submitFormAjax
* @private
* @param {Event} e Form submission event.
*/
AcceptOnBehalf.prototype.submitFormAjax = function(e) {
// We don't want to do a real form submission.
e.preventDefault();
// Convert all the form elements values to a serialised string.
var formData = this.modal.getRoot().find('form').serialize();
var requests = Ajax.call([{
methodname: 'tool_policy_submit_accept_on_behalf',
args: {jsonformdata: JSON.stringify(formData)}
}]);
requests[0].done(function(data) {
if (data.validationerrors) {
this.modal.setBody(this.getBody(formData));
} else {
this.close();
}
}.bind(this)).fail(Notification.exception);
};
/**
* This triggers a form submission, so that any mform elements can do final tricks before the form submission is processed.
*
* @method submitForm
* @param {Event} e Form submission event.
* @private
*/
AcceptOnBehalf.prototype.submitForm = function(e) {
e.preventDefault();
this.modal.getRoot().find('form').submit();
};
/**
* Close the modal
*/
AcceptOnBehalf.prototype.close = function() {
this.destroy();
document.location.reload();
};
/**
* Destroy the modal
*/
AcceptOnBehalf.prototype.destroy = function() {
FormChangeChecker.resetAllFormDirtyStates();
this.modal.destroy();
this.currentTrigger.focus();
};
return /** @alias module:tool_policy/acceptmodal */ {
// Public variables and functions.
/**
* Attach event listeners to initialise this module.
*
* @method init
* @param {int} contextid The contextid for the course.
* @return {AcceptOnBehalf}
*/
getInstance: function(contextid) {
return new AcceptOnBehalf(contextid);
}
};
});