MDL-76591 comment: implement new management interface elements.

Convert existing JS modules, call existing external service for
comment deletion.
This commit is contained in:
Paul Holden 2022-12-08 09:48:03 +00:00
parent 648b80c201
commit 35f3847064
11 changed files with 178 additions and 117 deletions

3
comment/amd/build/admin.min.js vendored Normal file
View File

@ -0,0 +1,3 @@
define("core_comment/admin",["exports","core/event_dispatcher","core/notification","core/pending","core/prefetch","core/str","core_comment/repository","core_reportbuilder/local/events","core_reportbuilder/local/selectors"],(function(_exports,_event_dispatcher,_notification,_pending,_prefetch,_str,_repository,reportEvents,reportSelectors){function _getRequireWildcardCache(nodeInterop){if("function"!=typeof WeakMap)return null;var cacheBabelInterop=new WeakMap,cacheNodeInterop=new WeakMap;return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop})(nodeInterop)}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule)return obj;if(null===obj||"object"!=typeof obj&&"function"!=typeof obj)return{default:obj};var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj))return cache.get(obj);var newObj={},hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj)if("default"!==key&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;desc&&(desc.get||desc.set)?Object.defineProperty(newObj,key,desc):newObj[key]=obj[key]}return newObj.default=obj,cache&&cache.set(obj,newObj),newObj}function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,_notification=_interopRequireDefault(_notification),_pending=_interopRequireDefault(_pending),reportEvents=_interopRequireWildcard(reportEvents),reportSelectors=_interopRequireWildcard(reportSelectors);const Selectors_commentDelete='[data-action="comment-delete"]',Selectors_commentDeleteChecked='[data-togglegroup="report-select-all"][data-toggle="slave"]:checked',Selectors_commentDeleteSelected='[data-action="comment-delete-selected"]';_exports.init=()=>{(0,_prefetch.prefetchStrings)("core_admin",["confirmdeletecomments"]),(0,_prefetch.prefetchStrings)("core",["delete","deleteselected"]),document.addEventListener("click",(event=>{const commentDelete=event.target.closest(Selectors_commentDelete);if(commentDelete){event.preventDefault();const triggerElement=commentDelete.closest(".dropdown").querySelector(".dropdown-toggle");_notification.default.saveCancelPromise((0,_str.get_string)("delete","core"),(0,_str.get_string)("confirmdeletecomments","core_admin"),(0,_str.get_string)("delete","core"),{triggerElement:triggerElement}).then((()=>{const pendingPromise=new _pending.default("core_comment/comment:delete"),reportElement=event.target.closest(reportSelectors.regions.report);return(0,_repository.deleteComment)(commentDelete.dataset.commentId).then((()=>((0,_event_dispatcher.dispatchEvent)(reportEvents.tableReload,{preservePagination:!0},reportElement),pendingPromise.resolve()))).catch(_notification.default.exception)})).catch((()=>{}))}const commentDeleteSelected=event.target.closest(Selectors_commentDeleteSelected);if(commentDeleteSelected){event.preventDefault();const reportElement=document.querySelector(reportSelectors.regions.report),commentDeleteChecked=reportElement.querySelectorAll(Selectors_commentDeleteChecked);if(0===commentDeleteChecked.length)return;_notification.default.saveCancelPromise((0,_str.get_string)("deleteselected","core"),(0,_str.get_string)("confirmdeletecomments","core_admin"),(0,_str.get_string)("delete","core"),{triggerElement:commentDeleteSelected}).then((()=>{const pendingPromise=new _pending.default("core_comment/comments:delete"),deleteCommentIds=[...commentDeleteChecked].map((check=>check.value));return(0,_repository.deleteComments)(deleteCommentIds).then((()=>((0,_event_dispatcher.dispatchEvent)(reportEvents.tableReload,{preservePagination:!0},reportElement),pendingPromise.resolve()))).catch(_notification.default.exception)})).catch((()=>{}))}}))}}));
//# sourceMappingURL=admin.min.js.map

File diff suppressed because one or more lines are too long

10
comment/amd/build/repository.min.js vendored Normal file
View File

@ -0,0 +1,10 @@
define("core_comment/repository",["exports","core/ajax"],(function(_exports,_ajax){var obj;
/**
* Module to handle comment AJAX requests
*
* @module core_comment/repository
* @copyright 2022 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.deleteComments=_exports.deleteComment=void 0,_ajax=(obj=_ajax)&&obj.__esModule?obj:{default:obj};_exports.deleteComment=comment=>deleteComments([comment]);const deleteComments=comments=>{const request={methodname:"core_comment_delete_comments",args:{comments:comments}};return _ajax.default.call([request])[0]};_exports.deleteComments=deleteComments}));
//# sourceMappingURL=repository.min.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"repository.min.js","sources":["../src/repository.js"],"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 * Module to handle comment AJAX requests\n *\n * @module core_comment/repository\n * @copyright 2022 Paul Holden <paulh@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Ajax from 'core/ajax';\n\n/**\n * Delete single comment\n *\n * @param {Number} comment Comment ID\n * @return {Promise}\n */\nexport const deleteComment = comment => deleteComments([comment]);\n\n/**\n * Delete multiple comments\n *\n * @param {Number[]} comments Comment IDs\n * @return {Promise}\n */\nexport const deleteComments = comments => {\n const request = {\n methodname: 'core_comment_delete_comments',\n args: {comments}\n };\n\n return Ajax.call([request])[0];\n};\n"],"names":["comment","deleteComments","comments","request","methodname","args","Ajax","call"],"mappings":";;;;;;;8LA+B6BA,SAAWC,eAAe,CAACD,gBAQ3CC,eAAiBC,iBACpBC,QAAU,CACZC,WAAY,+BACZC,KAAM,CAACH,SAAAA,kBAGJI,cAAKC,KAAK,CAACJ,UAAU"}

111
comment/amd/src/admin.js Normal file
View File

@ -0,0 +1,111 @@
// 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/>.
/**
* Comments admin management
*
* @module core_comment/admin
* @copyright 2022 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
"use strict";
import {dispatchEvent} from 'core/event_dispatcher';
import Notification from 'core/notification';
import Pending from 'core/pending';
import {prefetchStrings} from 'core/prefetch';
import {get_string as getString} from 'core/str';
import {deleteComment, deleteComments} from 'core_comment/repository';
import * as reportEvents from 'core_reportbuilder/local/events';
import * as reportSelectors from 'core_reportbuilder/local/selectors';
const Selectors = {
commentDelete: '[data-action="comment-delete"]',
commentDeleteChecked: '[data-togglegroup="report-select-all"][data-toggle="slave"]:checked',
commentDeleteSelected: '[data-action="comment-delete-selected"]',
};
/**
* Initialise module
*/
export const init = () => {
prefetchStrings('core_admin', [
'confirmdeletecomments',
]);
prefetchStrings('core', [
'delete',
'deleteselected'
]);
document.addEventListener('click', event => {
const commentDelete = event.target.closest(Selectors.commentDelete);
if (commentDelete) {
event.preventDefault();
// Use triggerElement to return focus to the action menu toggle.
const triggerElement = commentDelete.closest('.dropdown').querySelector('.dropdown-toggle');
Notification.saveCancelPromise(
getString('delete', 'core'),
getString('confirmdeletecomments', 'core_admin'),
getString('delete', 'core'),
{triggerElement}
).then(() => {
const pendingPromise = new Pending('core_comment/comment:delete');
const reportElement = event.target.closest(reportSelectors.regions.report);
return deleteComment(commentDelete.dataset.commentId)
.then(() => {
dispatchEvent(reportEvents.tableReload, {preservePagination: true}, reportElement);
return pendingPromise.resolve();
})
.catch(Notification.exception);
}).catch(() => {
return;
});
}
const commentDeleteSelected = event.target.closest(Selectors.commentDeleteSelected);
if (commentDeleteSelected) {
event.preventDefault();
const reportElement = document.querySelector(reportSelectors.regions.report);
const commentDeleteChecked = reportElement.querySelectorAll(Selectors.commentDeleteChecked);
if (commentDeleteChecked.length === 0) {
return;
}
Notification.saveCancelPromise(
getString('deleteselected', 'core'),
getString('confirmdeletecomments', 'core_admin'),
getString('delete', 'core'),
{triggerElement: commentDeleteSelected}
).then(() => {
const pendingPromise = new Pending('core_comment/comments:delete');
const deleteCommentIds = [...commentDeleteChecked].map(check => check.value);
return deleteComments(deleteCommentIds)
.then(() => {
dispatchEvent(reportEvents.tableReload, {preservePagination: true}, reportElement);
return pendingPromise.resolve();
})
.catch(Notification.exception);
}).catch(() => {
return;
});
}
});
};

View File

@ -0,0 +1,47 @@
// 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/>.
/**
* Module to handle comment AJAX requests
*
* @module core_comment/repository
* @copyright 2022 Paul Holden <paulh@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import Ajax from 'core/ajax';
/**
* Delete single comment
*
* @param {Number} comment Comment ID
* @return {Promise}
*/
export const deleteComment = comment => deleteComments([comment]);
/**
* Delete multiple comments
*
* @param {Number[]} comments Comment IDs
* @return {Promise}
*/
export const deleteComments = comments => {
const request = {
methodname: 'core_comment_delete_comments',
args: {comments}
};
return Ajax.call([request])[0];
};

View File

@ -439,74 +439,5 @@ M.core_comment = {
});
new CommentHelper(options);
},
init_admin: function(Y) {
var select_all = Y.one('#comment_select_all');
if (select_all) {
select_all.on('click', function(e) {
var comments = document.getElementsByName('comments');
var checked = false;
for (var i in comments) {
if (comments[i].checked) {
checked=true;
}
}
for (i in comments) {
comments[i].checked = !checked;
}
this.set('checked', !checked);
});
}
var comments_delete = Y.one('#comments_delete');
if (comments_delete) {
comments_delete.on('click', function(e) {
e.preventDefault();
var list = '';
var comments = document.getElementsByName('comments');
for (var i in comments) {
if (typeof comments[i] == 'object' && comments[i].checked) {
list += (comments[i].value + '-');
}
}
if (!list) {
return;
}
var args = {};
args.message = M.util.get_string('confirmdeletecomments', 'admin');
args.callback = function() {
var url = M.cfg.wwwroot + '/comment/index.php';
var data = {
'commentids': list,
'sesskey': M.cfg.sesskey,
'action': 'delete'
};
var cfg = {
method: 'POST',
on: {
complete: function(id,o,p) {
if (!o) {
alert('IO FATAL');
return;
}
if (o.responseText == 'yes') {
location.reload();
}
}
},
arguments: {
scope: this
},
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
},
data: build_querystring(data)
};
Y.io(url, cfg);
};
M.util.show_confirm_dialog(e, args);
});
}
}
};

View File

@ -18,63 +18,19 @@
/*
* Comments management interface
*
* @package core
* @package core_comment
* @copyright 2010 Dongsheng Cai {@link http://dongsheng.org}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
require_once('../config.php');
require_once($CFG->libdir.'/adminlib.php');
require_once($CFG->dirroot.'/comment/locallib.php');
use core_reportbuilder\system_report_factory;
use core_comment\reportbuilder\local\systemreports\comments;
admin_externalpage_setup('comments', '', null, '', array('pagelayout'=>'report'));
$PAGE->requires->js_init_call('M.core_comment.init_admin', null, true);
$action = optional_param('action', '', PARAM_ALPHA);
$commentid = optional_param('commentid', 0, PARAM_INT);
$commentids = optional_param('commentids', '', PARAM_ALPHANUMEXT);
$page = optional_param('page', 0, PARAM_INT);
$confirm = optional_param('confirm', 0, PARAM_INT);
$manager = new comment_manager();
if ($action and !confirm_sesskey()) {
// no action if sesskey not confirmed
$action = '';
}
if ($action === 'delete') {
// delete a single comment
if (!empty($commentid)) {
if (!$confirm) {
echo $OUTPUT->header();
$optionsyes = array('action'=>'delete', 'commentid'=>$commentid, 'confirm'=>1, 'sesskey'=>sesskey());
$optionsno = array('sesskey'=>sesskey());
$buttoncontinue = new single_button(new moodle_url('/comment/index.php', $optionsyes), get_string('delete'));
$buttoncancel = new single_button(new moodle_url('/comment/index.php', $optionsno), get_string('cancel'));
echo $OUTPUT->confirm(get_string('confirmdeletecomments', 'admin'), $buttoncontinue, $buttoncancel);
echo $OUTPUT->footer();
die;
} else {
if ($manager->delete_comment($commentid)) {
redirect($CFG->wwwroot.'/comment/');
} else {
$err = 'cannotdeletecomment';
}
}
}
// delete a list of comments
if (!empty($commentids)) {
if ($manager->delete_comments($commentids)) {
die('yes');
} else {
die('no');
}
}
}
$PAGE->requires->js_call_amd('core_comment/admin', 'init');
echo $OUTPUT->header();
echo $OUTPUT->heading(get_string('comments'));

View File

@ -400,7 +400,7 @@ $string['configyuicomboloading'] = 'This options enables combined file loading o
$string['confirmation'] = 'Confirmation';
$string['confirmcontextlock'] = '{$a->contextname} is currently unfrozen. Freezing it will make it read-only and prevent users from making changes. Are you sure you wish to continue?';
$string['confirmcontextunlock'] = '{$a->contextname} is currently frozen. Unfreezing it will allow users to make changes. Are you sure you wish to continue?';
$string['confirmdeletecomments'] = 'You are about to delete comments, are you sure?';
$string['confirmdeletecomments'] = 'Are you sure you want to delete the selected comment(s)?';
$string['confirmed'] = 'Confirmed';
$string['contactsitesupport'] = 'Contact site support';
$string['contextlocking'] = 'Context freezing';

View File

@ -384,6 +384,7 @@ $functions = array(
'methodname' => 'delete_comments',
'description' => 'Deletes a comment or comments.',
'type' => 'write',
'ajax' => true,
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE),
),
'core_completion_get_activities_completion_status' => array(

View File

@ -29,7 +29,7 @@
defined('MOODLE_INTERNAL') || die();
$version = 2023012600.00; // YYYYMMDD = weekly release date of this DEV branch.
$version = 2023012600.01; // YYYYMMDD = weekly release date of this DEV branch.
// RR = release increments - 00 in DEV branches.
// .XX = incremental changes.
$release = '4.2dev (Build: 20230126)'; // Human-friendly version name