Merge branch 'MDL-71090' of git://github.com/paulholden/moodle

This commit is contained in:
Sara Arjona
2021-04-15 11:56:40 +02:00
14 changed files with 261 additions and 273 deletions
+2
View File
@@ -0,0 +1,2 @@
define ("tool_dataprivacy/contactdpo",["exports","core_form/modalform","core/notification","core/str","core/toast"],function(a,b,c,d,e){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;b=f(b);c=f(c);function f(a){return a&&a.__esModule?a:{default:a}}var g={CONTACT_DPO:"[data-action=\"contactdpo\"]"};a.init=function init(){var a=document.querySelector(g.CONTACT_DPO);a.addEventListener("click",function(f){f.preventDefault();var g=new b.default({modalConfig:{title:(0,d.get_string)("contactdataprotectionofficer","tool_dataprivacy")},formClass:"tool_dataprivacy\\form\\contactdpo",saveButtonText:(0,d.get_string)("send","tool_dataprivacy"),returnFocus:a});g.addEventListener(g.events.FORM_SUBMITTED,function(a){if(a.detail.result){(0,d.get_string)("requestsubmitted","tool_dataprivacy").then(e.add).catch()}else{var b=a.detail.warnings.map(function(a){return a.message});c.default.addNotification({type:"error",message:b.join("<br>")})}});g.show()})}});
//# sourceMappingURL=contactdpo.min.js.map
@@ -0,0 +1 @@
{"version":3,"sources":["../src/contactdpo.js"],"names":["SELECTORS","CONTACT_DPO","init","triggerElement","document","querySelector","addEventListener","event","preventDefault","modalForm","ModalForm","modalConfig","title","formClass","saveButtonText","returnFocus","events","FORM_SUBMITTED","detail","result","then","addToast","catch","warningMessages","warnings","map","warning","message","Notification","addNotification","type","join","show"],"mappings":"oNAwBA,OACA,O,sDAIMA,CAAAA,CAAS,CAAG,CACdC,WAAW,CAAE,8BADC,C,QAOE,QAAPC,CAAAA,IAAO,EAAM,CACtB,GAAMC,CAAAA,CAAc,CAAGC,QAAQ,CAACC,aAAT,CAAuBL,CAAS,CAACC,WAAjC,CAAvB,CAEAE,CAAc,CAACG,gBAAf,CAAgC,OAAhC,CAAyC,SAAAC,CAAK,CAAI,CAC9CA,CAAK,CAACC,cAAN,GAEA,GAAMC,CAAAA,CAAS,CAAG,GAAIC,UAAJ,CAAc,CAC5BC,WAAW,CAAE,CACTC,KAAK,CAAE,iBAAU,8BAAV,CAA0C,kBAA1C,CADE,CADe,CAI5BC,SAAS,CAAE,oCAJiB,CAK5BC,cAAc,CAAE,iBAAU,MAAV,CAAkB,kBAAlB,CALY,CAM5BC,WAAW,CAAEZ,CANe,CAAd,CAAlB,CAUAM,CAAS,CAACH,gBAAV,CAA2BG,CAAS,CAACO,MAAV,CAAiBC,cAA5C,CAA4D,SAAAV,CAAK,CAAI,CACjE,GAAIA,CAAK,CAACW,MAAN,CAAaC,MAAjB,CAAyB,CACrB,iBAAU,kBAAV,CAA8B,kBAA9B,EAAkDC,IAAlD,CAAuDC,KAAvD,EAAiEC,KAAjE,EACH,CAFD,IAEO,CACH,GAAMC,CAAAA,CAAe,CAAGhB,CAAK,CAACW,MAAN,CAAaM,QAAb,CAAsBC,GAAtB,CAA0B,SAAAC,CAAO,QAAIA,CAAAA,CAAO,CAACC,OAAZ,CAAjC,CAAxB,CACAC,UAAaC,eAAb,CAA6B,CACzBC,IAAI,CAAE,OADmB,CAEzBH,OAAO,CAAEJ,CAAe,CAACQ,IAAhB,CAAqB,MAArB,CAFgB,CAA7B,CAIH,CACJ,CAVD,EAYAtB,CAAS,CAACuB,IAAV,EACH,CA1BD,CA2BH,C","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Javascript module for contacting the site DPO\n *\n * @module tool_dataprivacy/contactdpo\n * @package tool_dataprivacy\n * @copyright 2021 Paul Holden <[email protected]>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport ModalForm from 'core_form/modalform';\nimport Notification from 'core/notification';\nimport {get_string as getString} from 'core/str';\nimport {add as addToast} from 'core/toast';\n\nconst SELECTORS = {\n CONTACT_DPO: '[data-action=\"contactdpo\"]',\n};\n\n/**\n * Initialize module\n */\nexport const init = () => {\n const triggerElement = document.querySelector(SELECTORS.CONTACT_DPO);\n\n triggerElement.addEventListener('click', event => {\n event.preventDefault();\n\n const modalForm = new ModalForm({\n modalConfig: {\n title: getString('contactdataprotectionofficer', 'tool_dataprivacy'),\n },\n formClass: 'tool_dataprivacy\\\\form\\\\contactdpo',\n saveButtonText: getString('send', 'tool_dataprivacy'),\n returnFocus: triggerElement,\n });\n\n // Show a toast notification when the form is submitted.\n modalForm.addEventListener(modalForm.events.FORM_SUBMITTED, event => {\n if (event.detail.result) {\n getString('requestsubmitted', 'tool_dataprivacy').then(addToast).catch();\n } else {\n const warningMessages = event.detail.warnings.map(warning => warning.message);\n Notification.addNotification({\n type: 'error',\n message: warningMessages.join('<br>')\n });\n }\n });\n\n modalForm.show();\n });\n};\n"],"file":"contactdpo.min.js"}
+1 -1
View File
@@ -1,2 +1,2 @@
define ("tool_dataprivacy/myrequestactions",["jquery","core/ajax","core/notification","core/str","core/modal_factory","core/modal_events","core/templates","core/pending"],function(a,b,c,d,e,f,g,h){var j={CANCEL_REQUEST:"[data-action=\"cancel\"]",CONTACT_DPO:"[data-action=\"contactdpo\"]"},k=function(){this.registerEvents()};k.prototype.registerEvents=function(){a(j.CANCEL_REQUEST).click(function(g){g.preventDefault();var h=a(this).data("requestid");d.get_strings([{key:"cancelrequest",component:"tool_dataprivacy"},{key:"cancelrequestconfirmation",component:"tool_dataprivacy"}]).then(function(a){var d=a[0],g=a[1];return e.create({title:d,body:g,type:e.types.SAVE_CANCEL}).then(function(a){a.setSaveButtonText(d);a.getRoot().on(f.save,function(){b.call([{methodname:"tool_dataprivacy_cancel_data_request",args:{requestid:h}}])[0].done(function(a){if(a.result){window.location.reload()}else{c.addNotification({message:a.warnings[0].message,type:"error"})}}).fail(c.exception)});a.getRoot().on(f.hidden,function(){a.destroy()});return a})}).done(function(a){a.show()}).fail(c.exception)});a(j.CONTACT_DPO).click(function(b){var j=new h("dataprivacy/crud:initModal:contactdpo");b.preventDefault();var k=a(this).data("replytoemail"),l="";d.get_strings([{key:"contactdataprotectionofficer",component:"tool_dataprivacy"},{key:"send",component:"tool_dataprivacy"}]).then(function(a){var b=a[0];l=a[1];return e.create({title:b,body:g.render("tool_dataprivacy/contact_dpo",{replytoemail:k}),type:e.types.SAVE_CANCEL,large:!0})}).then(function(b){b.setSaveButtonText(l);b.show();b.getRoot().on(f.save,function(b){var c=a("#message").val().trim();if(0===c.length){b.preventDefault();a("[data-region=\"messageinput\"]").addClass("has-danger notifyproblem");a("#id_error_message").removeAttr("hidden")}else{i(c)}});b.getRoot().on(f.hidden,function(){b.destroy()})}).then(j.resolve).catch(c.exception)})};function i(a){var e="success";b.call([{methodname:"tool_dataprivacy_contact_dpo",args:{message:a}}])[0].then(function(a){if(a.result){return d.get_string("requestsubmitted","tool_dataprivacy")}e="error";return a.warnings.join("<br>")}).done(function(a){c.addNotification({message:a,type:e})}).fail(c.exception)}return{init:function init(){return new k}}});
define ("tool_dataprivacy/myrequestactions",["exports","core/ajax","core/notification","core/pending","core/str"],function(a,b,c,d,e){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;b=f(b);c=f(c);d=f(d);function f(a){return a&&a.__esModule?a:{default:a}}function g(a,b){return m(a)||l(a,b)||j(a,b)||h()}function h(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function j(a,b){if(!a)return;if("string"==typeof a)return k(a,b);var c=Object.prototype.toString.call(a).slice(8,-1);if("Object"===c&&a.constructor)c=a.constructor.name;if("Map"===c||"Set"===c)return Array.from(c);if("Arguments"===c||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(c))return k(a,b)}function k(a,b){if(null==b||b>a.length)b=a.length;for(var c=0,d=Array(b);c<b;c++){d[c]=a[c]}return d}function l(a,b){if("undefined"==typeof Symbol||!(Symbol.iterator in Object(a)))return;var c=[],d=!0,e=!1,f=void 0;try{for(var g=a[Symbol.iterator](),h;!(d=(h=g.next()).done);d=!0){c.push(h.value);if(b&&c.length===b)break}}catch(a){e=!0;f=a}finally{try{if(!d&&null!=g["return"])g["return"]()}finally{if(e)throw f}}return c}function m(a){if(Array.isArray(a))return a}var n={CANCEL_REQUEST:"[data-action=\"cancel\"][data-requestid]"};a.init=function init(){document.addEventListener("click",function(a){var f=a.target.closest(n.CANCEL_REQUEST);if(null===f){return}a.preventDefault();(0,e.get_strings)([{key:"cancelrequest",component:"tool_dataprivacy"},{key:"cancelrequestconfirmation",component:"tool_dataprivacy"}]).then(function(a){var e=g(a,2),h=e[0],i=e[1];return c.default.confirm(h,i,h,null,function(){var a=new d.default("tool/dataprivacy:cancelRequest"),e={methodname:"tool_dataprivacy_cancel_data_request",args:{requestid:f.dataset.requestid}};b.default.call([e])[0].then(function(b){if(b.result){window.location.reload()}else{c.default.addNotification({type:"error",message:b.warnings[0].message})}return a.resolve()}).catch(c.default.exception)})}).catch()})}});
//# sourceMappingURL=myrequestactions.min.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,67 @@
// 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/>.
/**
* Javascript module for contacting the site DPO
*
* @module tool_dataprivacy/contactdpo
* @package tool_dataprivacy
* @copyright 2021 Paul Holden <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import ModalForm from 'core_form/modalform';
import Notification from 'core/notification';
import {get_string as getString} from 'core/str';
import {add as addToast} from 'core/toast';
const SELECTORS = {
CONTACT_DPO: '[data-action="contactdpo"]',
};
/**
* Initialize module
*/
export const init = () => {
const triggerElement = document.querySelector(SELECTORS.CONTACT_DPO);
triggerElement.addEventListener('click', event => {
event.preventDefault();
const modalForm = new ModalForm({
modalConfig: {
title: getString('contactdataprotectionofficer', 'tool_dataprivacy'),
},
formClass: 'tool_dataprivacy\\form\\contactdpo',
saveButtonText: getString('send', 'tool_dataprivacy'),
returnFocus: triggerElement,
});
// Show a toast notification when the form is submitted.
modalForm.addEventListener(modalForm.events.FORM_SUBMITTED, event => {
if (event.detail.result) {
getString('requestsubmitted', 'tool_dataprivacy').then(addToast).catch();
} else {
const warningMessages = event.detail.warnings.map(warning => warning.message);
Notification.addNotification({
type: 'error',
message: warningMessages.join('<br>')
});
}
});
modalForm.show();
});
};
@@ -21,206 +21,53 @@
* @copyright 2018 Jun Pataleta
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
define([
'jquery',
'core/ajax',
'core/notification',
'core/str',
'core/modal_factory',
'core/modal_events',
'core/templates',
'core/pending'],
function($, Ajax, Notification, Str, ModalFactory, ModalEvents, Templates, Pending) {
/**
* List of action selectors.
*
* @type {{CANCEL_REQUEST: string}}
* @type {{CONTACT_DPO: string}}
*/
var ACTIONS = {
CANCEL_REQUEST: '[data-action="cancel"]',
CONTACT_DPO: '[data-action="contactdpo"]',
};
import Ajax from 'core/ajax';
import Notification from 'core/notification';
import Pending from 'core/pending';
import {get_strings as getStrings} from 'core/str';
/**
* MyRequestActions class.
*/
var MyRequestActions = function() {
this.registerEvents();
};
const SELECTORS = {
CANCEL_REQUEST: '[data-action="cancel"][data-requestid]',
};
/**
* Register event listeners.
*/
MyRequestActions.prototype.registerEvents = function() {
$(ACTIONS.CANCEL_REQUEST).click(function(e) {
e.preventDefault();
var requestId = $(this).data('requestid');
var stringkeys = [
{
key: 'cancelrequest',
component: 'tool_dataprivacy'
},
{
key: 'cancelrequestconfirmation',
component: 'tool_dataprivacy'
}
];
Str.get_strings(stringkeys).then(function(langStrings) {
var title = langStrings[0];
var confirmMessage = langStrings[1];
return ModalFactory.create({
title: title,
body: confirmMessage,
type: ModalFactory.types.SAVE_CANCEL
}).then(function(modal) {
modal.setSaveButtonText(title);
// Handle save event.
modal.getRoot().on(ModalEvents.save, function() {
// Cancel the request.
var params = {
'requestid': requestId
};
var request = {
methodname: 'tool_dataprivacy_cancel_data_request',
args: params
};
Ajax.call([request])[0].done(function(data) {
if (data.result) {
window.location.reload();
} else {
Notification.addNotification({
message: data.warnings[0].message,
type: 'error'
});
}
}).fail(Notification.exception);
});
// Handle hidden event.
modal.getRoot().on(ModalEvents.hidden, function() {
// Destroy when hidden.
modal.destroy();
});
return modal;
});
}).done(function(modal) {
// Show the modal!
modal.show();
}).fail(Notification.exception);
});
$(ACTIONS.CONTACT_DPO).click(function(e) {
var pendingPromise = new Pending('dataprivacy/crud:initModal:contactdpo');
e.preventDefault();
var replyToEmail = $(this).data('replytoemail');
var keys = [
{
key: 'contactdataprotectionofficer',
component: 'tool_dataprivacy'
},
{
key: 'send',
component: 'tool_dataprivacy'
},
];
var sendButtonText = '';
Str.get_strings(keys).then(function(langStrings) {
var modalTitle = langStrings[0];
sendButtonText = langStrings[1];
var context = {
'replytoemail': replyToEmail
};
return ModalFactory.create({
title: modalTitle,
body: Templates.render('tool_dataprivacy/contact_dpo', context),
type: ModalFactory.types.SAVE_CANCEL,
large: true
});
}).then(function(modal) {
modal.setSaveButtonText(sendButtonText);
// Show the modal!
modal.show();
// Handle send event.
modal.getRoot().on(ModalEvents.save, function(e) {
var message = $('#message').val().trim();
if (message.length === 0) {
e.preventDefault();
// Show validation error when the message is empty.
$('[data-region="messageinput"]').addClass('has-danger notifyproblem');
$('#id_error_message').removeAttr('hidden');
} else {
// Send the message.
sendMessageToDPO(message);
}
});
// Handle hidden event.
modal.getRoot().on(ModalEvents.hidden, function() {
// Destroy when hidden.
modal.destroy();
});
return;
}).then(pendingPromise.resolve)
.catch(Notification.exception);
});
};
/**
* Send message to the Data Protection Officer.
*
* @param {String} message The message to send.
*/
function sendMessageToDPO(message) {
var request = {
methodname: 'tool_dataprivacy_contact_dpo',
args: {
message: message
}
};
var requestType = 'success';
Ajax.call([request])[0].then(function(data) {
if (data.result) {
return Str.get_string('requestsubmitted', 'tool_dataprivacy');
}
requestType = 'error';
return data.warnings.join('<br>');
}).done(function(message) {
Notification.addNotification({
message: message,
type: requestType
});
}).fail(Notification.exception);
}
return /** @alias module:tool_dataprivacy/myrequestactions */ {
// Public variables and functions.
/**
* Initialise the unified user filter.
*
* @method init
* @return {MyRequestActions}
*/
'init': function() {
return new MyRequestActions();
/**
* Initialize module
*/
export const init = () => {
document.addEventListener('click', event => {
const triggerElement = event.target.closest(SELECTORS.CANCEL_REQUEST);
if (triggerElement === null) {
return;
}
};
});
event.preventDefault();
const requiredStrings = [
{key: 'cancelrequest', component: 'tool_dataprivacy'},
{key: 'cancelrequestconfirmation', component: 'tool_dataprivacy'},
];
getStrings(requiredStrings).then(([cancelRequest, cancelConfirm]) => {
return Notification.confirm(cancelRequest, cancelConfirm, cancelRequest, null, () => {
const pendingPromise = new Pending('tool/dataprivacy:cancelRequest');
const request = {
methodname: 'tool_dataprivacy_cancel_data_request',
args: {requestid: triggerElement.dataset.requestid}
};
Ajax.call([request])[0].then(response => {
if (response.result) {
window.location.reload();
} else {
Notification.addNotification({
type: 'error',
message: response.warnings[0].message
});
}
return pendingPromise.resolve();
}).catch(Notification.exception);
});
}).catch();
});
};
+2 -1
View File
@@ -212,7 +212,8 @@ class external extends external_api {
$warnings[] = [
'item' => $dpo->id,
'warningcode' => 'errorsendingtodpo',
'message' => get_string('errorsendingmessagetodpo', 'tool_dataprivacy')
'message' => get_string('errorsendingmessagetodpo', 'tool_dataprivacy',
fullname($dpo))
];
}
}
@@ -0,0 +1,100 @@
<?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/>.
namespace tool_dataprivacy\form;
use context;
use context_user;
use moodle_exception;
use moodle_url;
use core_form\dynamic_form;
use tool_dataprivacy\api;
use tool_dataprivacy\external;
/**
* Contact DPO modal form
*
* @package tool_dataprivacy
* @copyright 2021 Paul Holden <[email protected]>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class contactdpo extends dynamic_form {
/**
* Form definition
*/
protected function definition() {
global $USER;
$mform = $this->_form;
$mform->addElement('static', 'replyto', get_string('replyto', 'tool_dataprivacy'), s($USER->email));
$mform->addElement('textarea', 'message', get_string('message', 'tool_dataprivacy'), 'cols="60" rows="8"');
$mform->setType('message', PARAM_TEXT);
$mform->addRule('message', get_string('required'), 'required', null, 'client');
}
/**
* Return form context
*
* @return context
*/
protected function get_context_for_dynamic_submission(): context {
global $USER;
return context_user::instance($USER->id);
}
/**
* Check if current user has access to this form, otherwise throw exception
*
* @throws moodle_exception
*/
protected function check_access_for_dynamic_submission(): void {
if (!api::can_contact_dpo()) {
throw new moodle_exception('errorcontactdpodisabled', 'tool_dataprivacy');
}
}
/**
* Process the form submission, used if form was submitted via AJAX
*
* @return array
*/
public function process_dynamic_submission() {
return external::contact_dpo($this->get_data()->message);
}
/**
* Load in existing data as form defaults (not applicable)
*/
public function set_data_for_dynamic_submission(): void {
return;
}
/**
* Returns url to set in $PAGE->set_url() when form is being rendered or submitted via AJAX
*
* @return moodle_url
*/
protected function get_page_url_for_dynamic_submission(): moodle_url {
global $USER;
return new moodle_url('/user/profile.php', ['id' => $USER->id]);
}
}
@@ -55,14 +55,11 @@ class renderer extends plugin_renderer_base {
/**
* Render the contact DPO link.
*
* @param string $replytoemail The Reply-to email address
* @return string The HTML for the link.
* @throws coding_exception
*/
public function render_contact_dpo_link($replytoemail) {
public function render_contact_dpo_link() {
$params = [
'data-action' => 'contactdpo',
'data-replytoemail' => $replytoemail,
];
return html_writer::link('#', get_string('contactdataprotectionofficer', 'tool_dataprivacy'), $params);
}
@@ -135,6 +135,7 @@ $string['effectiveretentionperioduser'] = '{$a} (since the last time the user ac
$string['emailsalutation'] = 'Dear {$a},';
$string['errorcannotrequestdeleteforself'] = 'You don\'t have permission to create deletion request for yourself.';
$string['errorcannotrequestdeleteforother'] = 'You don\'t have permission to create deletion request for this user.';
$string['errorcontactdpodisabled'] = 'Contacting the privacy officer is disabled';
$string['errorinvalidrequestcomments'] = 'The comments field may contain plain text only.';
$string['errorinvalidrequestcreationmethod'] = 'Invalid request creation method!';
$string['errorinvalidrequeststatus'] = 'Invalid request status!';
+4 -2
View File
@@ -54,10 +54,12 @@ function tool_dataprivacy_myprofile_navigation(tree $tree, $user, $iscurrentuser
// Contact data protection officer link.
if (\tool_dataprivacy\api::can_contact_dpo() && $iscurrentuser) {
$renderer = $PAGE->get_renderer('tool_dataprivacy');
$content = $renderer->render_contact_dpo_link($USER->email);
$content = $renderer->render_contact_dpo_link();
$node = new core_user\output\myprofile\node('privacyandpolicies', 'contactdpo', null, null, null, $content);
$category->add_node($node);
$PAGE->requires->js_call_amd('tool_dataprivacy/myrequestactions', 'init');
// Require our Javascript module to handle contact DPO interaction.
$PAGE->requires->js_call_amd('tool_dataprivacy/contactdpo', 'init');
$url = new moodle_url('/admin/tool/dataprivacy/mydatarequests.php');
$node = new core_user\output\myprofile\node('privacyandpolicies', 'datarequests',
@@ -1,58 +0,0 @@
{{!
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/>.
}}
{{!
@template tool_dataprivacy/contact_dpo
The purpose of this template is to enable the user to contact the site's DPO via email.
Classes required for JS:
* none
Data attributes required for JS:
* none
Context variables required for this template:
* userid int The user's ID.
* email string The user's email address.
Example context (json):
{
"userid": 1,
"replytoemail": "[email protected]"
}
}}
<div class="container">
<div class="row mb-2">
<label class="col-md-3 col-form-label">{{#str}}replyto, tool_dataprivacy{{/str}}</label>
<div class="col-md-9 col-form-label">{{replytoemail}}</div>
</div>
<div class="row" data-region="messageinput">
<label for="message" class="col-md-3 col-form-label">
{{#str}}message, tool_dataprivacy{{/str}}
<span class="float-sm-right text-nowrap">
<abbr class="initialism text-danger" title="{{#str}}required{{/str}}">{{#pix}}req, core, {{#str}}required{{/str}}{{/pix}}</abbr>
</span>
</label>
<div class="col-md-9">
<textarea class="form-control" id="message" cols="60" rows="8"></textarea>
<div class="form-control-feedback" id="id_error_message" hidden="hidden">
{{#str}}required, moodle{{/str}}
</div>
</div>
</div>
</div>
@@ -8,19 +8,21 @@ Feature: Contact the privacy officer
Given the following "users" exist:
| username | firstname | lastname | email |
| student1 | Student | 1 | s1@example.com |
And I log in as "admin"
And I set the following administration settings values:
| contactdataprotectionofficer | 1 |
And I log out
@javascript
Scenario: Contacting the privacy officer
Given I log in as "student1"
Given the following config values are set as admin:
| contactdataprotectionofficer | 1 | tool_dataprivacy |
When I log in as "student1"
And I follow "Profile" in the user menu
And I should see "Contact the privacy officer"
And I click on "Contact the privacy officer" "link"
And I set the field "Message" to "Hello DPO!"
And I click on "Send" "button" in the "Contact the privacy officer" "dialogue"
And I should see "Your request has been submitted to the privacy officer"
Then I should see "Your request has been submitted to the privacy officer"
And I click on "Data requests" "link"
And I should see "Hello DPO!" in the "General inquiry" "table_row"
Scenario: Contacting the privacy officer when not enabled
When I log in as "student1"
And I follow "Profile" in the user menu
Then "Contact the privacy officer" "link" should not exist
@@ -0,0 +1,26 @@
@tool @tool_dataprivacy
Feature: Manage my own data requests
In order to manage my own data requests
As a user
I need to be able to view and cancel all my data requests
Background:
Given the following "users" exist:
| username | firstname | lastname | email |
| student1 | Student | 1 | s1@example.com |
And the following config values are set as admin:
| contactdataprotectionofficer | 1 | tool_dataprivacy |
@javascript
Scenario: Cancel my own data request
Given I log in as "student1"
And I follow "Profile" in the user menu
And I click on "Contact the privacy officer" "link"
And I set the field "Message" to "Hello DPO!"
And I click on "Send" "button" in the "Contact the privacy officer" "dialogue"
And I should see "Your request has been submitted to the privacy officer"
When I click on "Data requests" "link"
And I open the action menu in "Hello DPO!" "table_row"
And I choose "Cancel" in the open action menu
And I click on "Cancel request" "button" in the "Cancel request" "dialogue"
Then I should see "Cancelled" in the "Hello DPO!" "table_row"