mirror of
https://github.com/moodle/moodle.git
synced 2025-03-14 20:50:21 +01:00
MDL-74054 qbank_columnsortorder: Implement add, remove and resize
This updates the admin interface, and hooks into the question bank view for users to override admin defaults with their preferences.
This commit is contained in:
parent
6001ee3dfd
commit
37d69fff6b
98
question/bank/columnsortorder/actions.php
Normal file
98
question/bank/columnsortorder/actions.php
Normal file
@ -0,0 +1,98 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Actions controller
|
||||
*
|
||||
* Perform a synchronous action to modify the question bank UI and redirect back to the previous page.
|
||||
* These features are mostly progressively enhanced by actions.js and web services, but this remains as a fallback.
|
||||
*
|
||||
* @package qbank_columnsortorder
|
||||
* @copyright 2023 onwards Catalyst IT EU {@link https://catalyst-eu.net}
|
||||
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
require_once(__DIR__ . '/../../../config.php');
|
||||
|
||||
$action = required_param('action', PARAM_TEXT);
|
||||
$global = optional_param('global', false, PARAM_BOOL);
|
||||
$returnurl = optional_param('returnurl', '/question/bank/columnsortorder/sortcolumns.php', PARAM_LOCALURL);
|
||||
|
||||
require_login();
|
||||
|
||||
if ($global) {
|
||||
require_capability('moodle/site:config', context_system::instance());
|
||||
}
|
||||
|
||||
if ($action === 'debugreset' && $CFG->debug === DEBUG_DEVELOPER) {
|
||||
$columnmanager = new \qbank_columnsortorder\column_manager($global);
|
||||
$columnmanager::set_hidden_columns([], $global);
|
||||
$columnmanager::set_column_order([], $global);
|
||||
$columnmanager::set_column_size('', $global);
|
||||
redirect(new moodle_url($returnurl));
|
||||
}
|
||||
|
||||
require_sesskey();
|
||||
$columnmanager = new \qbank_columnsortorder\column_manager($global);
|
||||
switch ($action) {
|
||||
case 'add':
|
||||
case 'remove':
|
||||
$column = required_param('column', PARAM_RAW);
|
||||
[$columnclass, ] = explode(\core_question\local\bank\column_base::ID_SEPARATOR, $column);
|
||||
if (!class_exists($columnclass)) {
|
||||
throw new invalid_parameter_exception("'{$columnclass}' is not a valid column class.");
|
||||
}
|
||||
$hiddencolumns = $columnmanager->hiddencolumns;
|
||||
if ($action === 'add') {
|
||||
$key = array_search($column, $hiddencolumns);
|
||||
if ($key !== false) {
|
||||
unset($hiddencolumns[$key]);
|
||||
}
|
||||
} else {
|
||||
if (!in_array($column, $hiddencolumns)) {
|
||||
$hiddencolumns[] = $column;
|
||||
}
|
||||
}
|
||||
$columnmanager::set_hidden_columns($hiddencolumns, $global);
|
||||
break;
|
||||
|
||||
case 'savewidths':
|
||||
$rawwidths = optional_param_array('width', [], PARAM_INT);
|
||||
$widths = [];
|
||||
foreach (array_filter($rawwidths) as $escapedclass => $width) {
|
||||
$class = str_replace('__', '\\', $escapedclass);
|
||||
// Validate that the class exists and the width is valid.
|
||||
// Since the browser uses Constraint Validation to prevent the form being submitted with an invalid width,
|
||||
// the only way we'll get one here is if someone is messing around, so don't worry about re-displaying the
|
||||
// form with an error message, just ignore the invalid value.
|
||||
if (class_exists($class) && $width >= 10) {
|
||||
$widths[] = (object)[
|
||||
'column' => $class,
|
||||
'width' => $width,
|
||||
];
|
||||
}
|
||||
}
|
||||
$columnmanager::set_column_size(json_encode($widths), $global);
|
||||
break;
|
||||
|
||||
case 'reset':
|
||||
$columnmanager::set_hidden_columns([], $global);
|
||||
$columnmanager::set_column_order([], $global);
|
||||
$columnmanager::set_column_size('', $global);
|
||||
break;
|
||||
}
|
||||
redirect(new moodle_url($returnurl));
|
11
question/bank/columnsortorder/amd/build/actions.min.js
vendored
Normal file
11
question/bank/columnsortorder/amd/build/actions.min.js
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
define("qbank_columnsortorder/actions",["exports","core/sortable_list","jquery","qbank_columnsortorder/repository","core/notification","core/fragment","core/templates"],(function(_exports,_sortable_list,_jquery,repository,_notification,_fragment,_templates){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 _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}
|
||||
/**
|
||||
* Common javascript for handling actions on the admin page and the user's view of the question bank.
|
||||
*
|
||||
* @module qbank_columnsortorder/actions
|
||||
* @copyright 2023 onwards Catalyst IT Europe Ltd
|
||||
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.setupSortableLists=_exports.setupActionButtons=_exports.getColumnOrder=_exports.SELECTORS=void 0,_sortable_list=_interopRequireDefault(_sortable_list),_jquery=_interopRequireDefault(_jquery),repository=function(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]}newObj.default=obj,cache&&cache.set(obj,newObj);return newObj}(repository),_notification=_interopRequireDefault(_notification),_fragment=_interopRequireDefault(_fragment),_templates=_interopRequireDefault(_templates);const SELECTORS={columnList:".qbank-column-list",sortableColumn:".qbank-sortable-column",removeLink:"[data-action=remove]",moveHandler:"[data-drag-type=move]",addColumn:".addcolumn",addLink:"[data-action=add]",actionLink:".action-link"};_exports.SELECTORS=SELECTORS;_exports.setupSortableLists=function(listRoot){let vertical=arguments.length>1&&void 0!==arguments[1]&&arguments[1],global=arguments.length>2&&void 0!==arguments[2]&&arguments[2];const sortableList=new _sortable_list.default(listRoot,{moveHandlerSelector:SELECTORS.moveHandler,isHorizontal:!vertical});sortableList.getElementName=element=>Promise.resolve(element.data("name"));const sortableColumns=(0,_jquery.default)(SELECTORS.sortableColumn);return sortableColumns.on(_sortable_list.default.EVENTS.DROP,(()=>{repository.setColumnbankOrder(getColumnOrder(listRoot),global).catch(_notification.default.exception),listRoot.querySelectorAll(SELECTORS.sortableColumn).forEach((item=>item.classList.remove("active")))})),sortableColumns.on(_sortable_list.default.EVENTS.DRAGSTART,(event=>{event.currentTarget.classList.add("active")})),sortableColumns};_exports.setupActionButtons=function(uiRoot){let global=arguments.length>1&&void 0!==arguments[1]&&arguments[1];uiRoot.addEventListener("click",(async e=>{const actionLink=e.target.closest(SELECTORS.actionLink);if(actionLink)try{e.preventDefault();const action=actionLink.dataset.action;if("add"===action||"remove"===action){const hiddenColumns=[],addColumnList=document.querySelector(SELECTORS.addColumn);addColumnList&&addColumnList.querySelectorAll(SELECTORS.addLink).forEach((item=>{"add"===action&&item===actionLink||hiddenColumns.push(item.dataset.column)})),"remove"===action&&hiddenColumns.push(actionLink.dataset.column),await repository.setHiddenColumns(hiddenColumns,global)}else"reset"===action&&await Promise.all([repository.setColumnbankOrder([],global),repository.setHiddenColumns([],global),repository.setColumnSize("",global)]);const fragmentData=uiRoot.dataset;_fragment.default.loadFragment(fragmentData.component,fragmentData.callback,fragmentData.contextid).then(((html,js)=>_templates.default.replaceNode(uiRoot,html,js))).catch(_notification.default.exception)}catch(ex){await _notification.default.exception(ex)}}))};const getColumnOrder=listRoot=>{const columns=Array.from(listRoot.querySelectorAll("[data-columnid]")).map((column=>column.dataset.columnid));return columns.filter(((value,index)=>columns.indexOf(value)===index))};_exports.getColumnOrder=getColumnOrder}));
|
||||
|
||||
//# sourceMappingURL=actions.min.js.map
|
File diff suppressed because one or more lines are too long
11
question/bank/columnsortorder/amd/build/admin_actions.min.js
vendored
Normal file
11
question/bank/columnsortorder/amd/build/admin_actions.min.js
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
define("qbank_columnsortorder/admin_actions",["exports","qbank_columnsortorder/actions","qbank_columnsortorder/repository","core/notification","core/pending"],(function(_exports,actions,repository,_notification,_pending){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}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}
|
||||
/**
|
||||
* Javascript for handling actions on the admin page
|
||||
*
|
||||
* @module qbank_columnsortorder/admin_actions
|
||||
* @copyright 2023 onwards Catalyst IT Europe Ltd
|
||||
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.init=void 0,actions=_interopRequireWildcard(actions),repository=_interopRequireWildcard(repository),_notification=_interopRequireDefault(_notification),_pending=_interopRequireDefault(_pending);_exports.init=id=>{const uiRoot=document.getElementById(id),listRoot=uiRoot.querySelector(actions.SELECTORS.columnList);actions.setupSortableLists(listRoot,!0,!0),actions.setupActionButtons(uiRoot,!0),(listRoot=>{listRoot.addEventListener("change",(async()=>{const pendingPromise=new _pending.default("saveWidths"),columns=listRoot.querySelectorAll(actions.SELECTORS.sortableColumn),widths=[];columns.forEach((column=>{const widthInput=column.querySelector(".width-input"),valid=widthInput.checkValidity();widthInput.closest(".has-validation").classList.add("was-validated"),valid&&widths.push({column:column.dataset.columnid,width:widthInput.value})})),await repository.setColumnSize(JSON.stringify(widths),!0).catch(_notification.default.exception),pendingPromise.resolve()}))})(listRoot)}}));
|
||||
|
||||
//# sourceMappingURL=admin_actions.min.js.map
|
@ -0,0 +1 @@
|
||||
{"version":3,"file":"admin_actions.min.js","sources":["../src/admin_actions.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 * Javascript for handling actions on the admin page\n *\n * @module qbank_columnsortorder/admin_actions\n * @copyright 2023 onwards Catalyst IT Europe Ltd\n * @author Mark Johnson <mark.johnson@catalyst-eu.net>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport * as actions from 'qbank_columnsortorder/actions';\nimport * as repository from 'qbank_columnsortorder/repository';\nimport Notification from \"core/notification\";\nimport Pending from 'core/pending';\n\n/**\n * Event handler to save the custom column widths when a field is edited.\n *\n * @param {Element} listRoot The root element of the list of columns.\n */\nconst setupSaveWidths = listRoot => {\n listRoot.addEventListener('change', async() => {\n const pendingPromise = new Pending('saveWidths');\n const columns = listRoot.querySelectorAll(actions.SELECTORS.sortableColumn);\n const widths = [];\n columns.forEach(column => {\n const widthInput = column.querySelector('.width-input');\n const valid = widthInput.checkValidity();\n widthInput.closest('.has-validation').classList.add('was-validated');\n if (!valid) {\n return;\n }\n widths.push({\n column: column.dataset.columnid,\n width: widthInput.value,\n });\n });\n await repository.setColumnSize(JSON.stringify(widths), true).catch(Notification.exception);\n pendingPromise.resolve();\n });\n};\n\n/**\n * Initialize module\n *\n * Set up event handlers for the action buttons, width fields and initialise column sorting.\n *\n * @param {String} id ID for the admin UI root element.\n */\nexport const init = id => {\n const uiRoot = document.getElementById(id);\n const listRoot = uiRoot.querySelector(actions.SELECTORS.columnList);\n actions.setupSortableLists(listRoot, true, true);\n actions.setupActionButtons(uiRoot, true);\n setupSaveWidths(listRoot);\n};\n"],"names":["id","uiRoot","document","getElementById","listRoot","querySelector","actions","SELECTORS","columnList","setupSortableLists","setupActionButtons","addEventListener","async","pendingPromise","Pending","columns","querySelectorAll","sortableColumn","widths","forEach","column","widthInput","valid","checkValidity","closest","classList","add","push","dataset","columnid","width","value","repository","setColumnSize","JSON","stringify","catch","Notification","exception","resolve","setupSaveWidths"],"mappings":";;;;;;;;sRA+DoBA,WACVC,OAASC,SAASC,eAAeH,IACjCI,SAAWH,OAAOI,cAAcC,QAAQC,UAAUC,YACxDF,QAAQG,mBAAmBL,UAAU,GAAM,GAC3CE,QAAQI,mBAAmBT,QAAQ,GAjCfG,CAAAA,WACpBA,SAASO,iBAAiB,UAAUC,gBAC1BC,eAAiB,IAAIC,iBAAQ,cAC7BC,QAAUX,SAASY,iBAAiBV,QAAQC,UAAUU,gBACtDC,OAAS,GACfH,QAAQI,SAAQC,eACNC,WAAaD,OAAOf,cAAc,gBAClCiB,MAAQD,WAAWE,gBACzBF,WAAWG,QAAQ,mBAAmBC,UAAUC,IAAI,iBAC/CJ,OAGLJ,OAAOS,KAAK,CACRP,OAAQA,OAAOQ,QAAQC,SACvBC,MAAOT,WAAWU,iBAGpBC,WAAWC,cAAcC,KAAKC,UAAUjB,SAAS,GAAMkB,MAAMC,sBAAaC,WAChFzB,eAAe0B,cAgBnBC,CAAgBpC"}
|
3
question/bank/columnsortorder/amd/build/repository.min.js
vendored
Normal file
3
question/bank/columnsortorder/amd/build/repository.min.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
define("qbank_columnsortorder/repository",["exports","core/ajax"],(function(_exports,_ajax){Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.setHiddenColumns=_exports.setColumnbankOrder=_exports.setColumnSize=void 0;_exports.setHiddenColumns=function(columns){let global=arguments.length>1&&void 0!==arguments[1]&&arguments[1];const responses=(0,_ajax.call)([{methodname:"qbank_columnsortorder_set_hidden_columns",args:{columns:columns,global:global}}]);return responses[0]};_exports.setColumnbankOrder=function(columns){let global=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return(0,_ajax.call)([{methodname:"qbank_columnsortorder_set_columnbank_order",args:{columns:columns,global:global}}])[0]};_exports.setColumnSize=function(sizes){let global=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return(0,_ajax.call)([{methodname:"qbank_columnsortorder_set_column_size",args:{sizes:sizes,global:global}}])[0]}}));
|
||||
|
||||
//# sourceMappingURL=repository.min.js.map
|
@ -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 * External function calls for qbank_columnsortorder\n *\n * @module qbank_columnsortorder/repository\n * @copyright 2023 Catalyst IT Europe Ltd.\n * @author Mark Johnson <mark.johnson@catalyst-eu.net>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport {call as fetchMany} from 'core/ajax';\n\n/**\n * Save the list of hidden columns\n *\n * @param {String[]} columns List of hidden column names\n * @param {Boolean} global Set global config setting, rather than user preference\n * @return {Promise}\n */\nexport const setHiddenColumns = (columns, global = false) => {\n const responses = fetchMany([{\n methodname: 'qbank_columnsortorder_set_hidden_columns',\n args: {columns: columns, global: global},\n }]);\n return responses[0];\n};\n\n/**\n * Save the order of columns\n *\n * @param {String[]} columns List of column names in the desired order\n * @param {Boolean} global Set global config setting, rather than user preference\n * @return {Promise}\n */\nexport const setColumnbankOrder = (columns, global = false) => {\n return fetchMany([{\n methodname: 'qbank_columnsortorder_set_columnbank_order',\n args: {columns: columns, global: global},\n }])[0];\n};\n\n/**\n * Save the column widths\n *\n * @param {String} sizes JSON string encoding an array of objects with \"column\" and \"width\" properties.\n * @param {Boolean} global Set global config setting, rather than user preference\n * @return {Promise}\n */\nexport const setColumnSize = (sizes, global = false) => {\n return fetchMany([{\n methodname: 'qbank_columnsortorder_set_column_size',\n args: {sizes: sizes, global: global},\n }])[0];\n};\n"],"names":["columns","global","responses","methodname","args","sizes"],"mappings":"kQAiCgC,SAACA,aAASC,qEAChCC,WAAY,cAAU,CAAC,CACzBC,WAAY,2CACZC,KAAM,CAACJ,QAASA,QAASC,OAAQA,kBAE9BC,UAAU,gCAUa,SAACF,aAASC,sEACjC,cAAU,CAAC,CACdE,WAAY,6CACZC,KAAM,CAACJ,QAASA,QAASC,OAAQA,WACjC,2BAUqB,SAACI,WAAOJ,sEAC1B,cAAU,CAAC,CACdE,WAAY,wCACZC,KAAM,CAACC,MAAOA,MAAOJ,OAAQA,WAC7B"}
|
11
question/bank/columnsortorder/amd/build/user_actions.min.js
vendored
Normal file
11
question/bank/columnsortorder/amd/build/user_actions.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
134
question/bank/columnsortorder/amd/src/actions.js
Normal file
134
question/bank/columnsortorder/amd/src/actions.js
Normal file
@ -0,0 +1,134 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* Common javascript for handling actions on the admin page and the user's view of the question bank.
|
||||
*
|
||||
* @module qbank_columnsortorder/actions
|
||||
* @copyright 2023 onwards Catalyst IT Europe Ltd
|
||||
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
import SortableList from 'core/sortable_list';
|
||||
import $ from 'jquery';
|
||||
import * as repository from 'qbank_columnsortorder/repository';
|
||||
import Notification from "core/notification";
|
||||
import Fragment from "core/fragment";
|
||||
import Templates from "core/templates";
|
||||
|
||||
export const SELECTORS = {
|
||||
columnList: '.qbank-column-list',
|
||||
sortableColumn: '.qbank-sortable-column',
|
||||
removeLink: '[data-action=remove]',
|
||||
moveHandler: '[data-drag-type=move]',
|
||||
addColumn: '.addcolumn',
|
||||
addLink: '[data-action=add]',
|
||||
actionLink: '.action-link',
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets up sortable list in the column sort order page.
|
||||
*
|
||||
* @param {Element} listRoot Element containing the sortable list.
|
||||
* @param {Boolean} vertical Is the list in vertical orientation, rather than horizonal?
|
||||
* @param {Boolean} global Should changes be saved to global config, rather than user preferences?
|
||||
* @return {jQuery} sortable column elements, for attaching additional event listeners.
|
||||
*/
|
||||
export const setupSortableLists = (listRoot, vertical = false, global = false) => {
|
||||
const sortableList = new SortableList(listRoot, {
|
||||
moveHandlerSelector: SELECTORS.moveHandler,
|
||||
isHorizontal: !vertical,
|
||||
});
|
||||
sortableList.getElementName = element => Promise.resolve(element.data('name'));
|
||||
|
||||
const sortableColumns = $(SELECTORS.sortableColumn);
|
||||
|
||||
sortableColumns.on(SortableList.EVENTS.DROP, () => {
|
||||
repository.setColumnbankOrder(getColumnOrder(listRoot), global).catch(Notification.exception);
|
||||
listRoot.querySelectorAll(SELECTORS.sortableColumn).forEach(item => item.classList.remove('active'));
|
||||
});
|
||||
|
||||
sortableColumns.on(SortableList.EVENTS.DRAGSTART, (event) => {
|
||||
event.currentTarget.classList.add('active');
|
||||
});
|
||||
|
||||
return sortableColumns;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set up event handlers for action buttons.
|
||||
*
|
||||
* For each action, call the web service to update the appropriate setting or user preference, then call the fragment to
|
||||
* refresh the view.
|
||||
*
|
||||
* @param {Element} uiRoot The root of the question bank UI.
|
||||
* @param {Boolean} global Should changes be saved to global config, rather than user preferences?
|
||||
*/
|
||||
export const setupActionButtons = (uiRoot, global = false) => {
|
||||
uiRoot.addEventListener('click', async(e) => {
|
||||
const actionLink = e.target.closest(SELECTORS.actionLink);
|
||||
if (!actionLink) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
e.preventDefault();
|
||||
const action = actionLink.dataset.action;
|
||||
if (action === 'add' || action === 'remove') {
|
||||
const hiddenColumns = [];
|
||||
const addColumnList = document.querySelector(SELECTORS.addColumn);
|
||||
if (addColumnList) {
|
||||
addColumnList.querySelectorAll(SELECTORS.addLink).forEach(item => {
|
||||
if (action === 'add' && item === actionLink) {
|
||||
return;
|
||||
}
|
||||
hiddenColumns.push(item.dataset.column);
|
||||
});
|
||||
}
|
||||
if (action === 'remove') {
|
||||
hiddenColumns.push(actionLink.dataset.column);
|
||||
}
|
||||
await repository.setHiddenColumns(hiddenColumns, global);
|
||||
} else if (action === 'reset') {
|
||||
await Promise.all([
|
||||
repository.setColumnbankOrder([], global),
|
||||
repository.setHiddenColumns([], global),
|
||||
repository.setColumnSize('', global),
|
||||
]);
|
||||
}
|
||||
const fragmentData = uiRoot.dataset;
|
||||
// We have to use then() there, as loadFragment doesn't appear to work with await.
|
||||
Fragment.loadFragment(fragmentData.component, fragmentData.callback, fragmentData.contextid)
|
||||
.then((html, js) => {
|
||||
return Templates.replaceNode(uiRoot, html, js);
|
||||
})
|
||||
.catch(Notification.exception);
|
||||
} catch (ex) {
|
||||
await Notification.exception(ex);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the newly reordered columns to display in the question bank view.
|
||||
* @param {Element} listRoot
|
||||
* @returns {Array}
|
||||
*/
|
||||
export const getColumnOrder = listRoot => {
|
||||
const columns = Array.from(listRoot.querySelectorAll('[data-columnid]'))
|
||||
.map(column => column.dataset.columnid);
|
||||
|
||||
return columns.filter((value, index) => columns.indexOf(value) === index);
|
||||
};
|
70
question/bank/columnsortorder/amd/src/admin_actions.js
Normal file
70
question/bank/columnsortorder/amd/src/admin_actions.js
Normal file
@ -0,0 +1,70 @@
|
||||
// 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 for handling actions on the admin page
|
||||
*
|
||||
* @module qbank_columnsortorder/admin_actions
|
||||
* @copyright 2023 onwards Catalyst IT Europe Ltd
|
||||
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
import * as actions from 'qbank_columnsortorder/actions';
|
||||
import * as repository from 'qbank_columnsortorder/repository';
|
||||
import Notification from "core/notification";
|
||||
import Pending from 'core/pending';
|
||||
|
||||
/**
|
||||
* Event handler to save the custom column widths when a field is edited.
|
||||
*
|
||||
* @param {Element} listRoot The root element of the list of columns.
|
||||
*/
|
||||
const setupSaveWidths = listRoot => {
|
||||
listRoot.addEventListener('change', async() => {
|
||||
const pendingPromise = new Pending('saveWidths');
|
||||
const columns = listRoot.querySelectorAll(actions.SELECTORS.sortableColumn);
|
||||
const widths = [];
|
||||
columns.forEach(column => {
|
||||
const widthInput = column.querySelector('.width-input');
|
||||
const valid = widthInput.checkValidity();
|
||||
widthInput.closest('.has-validation').classList.add('was-validated');
|
||||
if (!valid) {
|
||||
return;
|
||||
}
|
||||
widths.push({
|
||||
column: column.dataset.columnid,
|
||||
width: widthInput.value,
|
||||
});
|
||||
});
|
||||
await repository.setColumnSize(JSON.stringify(widths), true).catch(Notification.exception);
|
||||
pendingPromise.resolve();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize module
|
||||
*
|
||||
* Set up event handlers for the action buttons, width fields and initialise column sorting.
|
||||
*
|
||||
* @param {String} id ID for the admin UI root element.
|
||||
*/
|
||||
export const init = id => {
|
||||
const uiRoot = document.getElementById(id);
|
||||
const listRoot = uiRoot.querySelector(actions.SELECTORS.columnList);
|
||||
actions.setupSortableLists(listRoot, true, true);
|
||||
actions.setupActionButtons(uiRoot, true);
|
||||
setupSaveWidths(listRoot);
|
||||
};
|
68
question/bank/columnsortorder/amd/src/repository.js
Normal file
68
question/bank/columnsortorder/amd/src/repository.js
Normal file
@ -0,0 +1,68 @@
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* External function calls for qbank_columnsortorder
|
||||
*
|
||||
* @module qbank_columnsortorder/repository
|
||||
* @copyright 2023 Catalyst IT Europe Ltd.
|
||||
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
import {call as fetchMany} from 'core/ajax';
|
||||
|
||||
/**
|
||||
* Save the list of hidden columns
|
||||
*
|
||||
* @param {String[]} columns List of hidden column names
|
||||
* @param {Boolean} global Set global config setting, rather than user preference
|
||||
* @return {Promise}
|
||||
*/
|
||||
export const setHiddenColumns = (columns, global = false) => {
|
||||
const responses = fetchMany([{
|
||||
methodname: 'qbank_columnsortorder_set_hidden_columns',
|
||||
args: {columns: columns, global: global},
|
||||
}]);
|
||||
return responses[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* Save the order of columns
|
||||
*
|
||||
* @param {String[]} columns List of column names in the desired order
|
||||
* @param {Boolean} global Set global config setting, rather than user preference
|
||||
* @return {Promise}
|
||||
*/
|
||||
export const setColumnbankOrder = (columns, global = false) => {
|
||||
return fetchMany([{
|
||||
methodname: 'qbank_columnsortorder_set_columnbank_order',
|
||||
args: {columns: columns, global: global},
|
||||
}])[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* Save the column widths
|
||||
*
|
||||
* @param {String} sizes JSON string encoding an array of objects with "column" and "width" properties.
|
||||
* @param {Boolean} global Set global config setting, rather than user preference
|
||||
* @return {Promise}
|
||||
*/
|
||||
export const setColumnSize = (sizes, global = false) => {
|
||||
return fetchMany([{
|
||||
methodname: 'qbank_columnsortorder_set_column_size',
|
||||
args: {sizes: sizes, global: global},
|
||||
}])[0];
|
||||
};
|
367
question/bank/columnsortorder/amd/src/user_actions.js
Normal file
367
question/bank/columnsortorder/amd/src/user_actions.js
Normal file
@ -0,0 +1,367 @@
|
||||
// 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 for customising the user's view of the question bank
|
||||
*
|
||||
* @module qbank_columnsortorder/user_actions
|
||||
* @copyright 2021 Catalyst IT Australia Pty Ltd
|
||||
* @author Ghaly Marc-Alexandre <marc-alexandreghaly@catalyst-ca.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
import * as actions from 'qbank_columnsortorder/actions';
|
||||
import * as repository from 'qbank_columnsortorder/repository';
|
||||
import {get_string as getString} from 'core/str';
|
||||
import ModalEvents from 'core/modal_events';
|
||||
import ModalFactory from 'core/modal_factory';
|
||||
import Notification from "core/notification";
|
||||
import SortableList from 'core/sortable_list';
|
||||
import Templates from "core/templates";
|
||||
|
||||
|
||||
const SELECTORS = {
|
||||
uiRoot: '.questionbankwindow',
|
||||
moveAction: '.menu-action[data-action=move]',
|
||||
resizeAction: '.menu-action[data-action=resize]',
|
||||
resizeHandle: '.qbank_columnsortorder-action-handle.resize',
|
||||
handleContainer: '.handle-container',
|
||||
headerContainer: '.header-container',
|
||||
tableColumn: identifier => `td[data-columnid="${identifier.replace(/["\\]/g, '\\$&')}"]`,
|
||||
};
|
||||
|
||||
/** To track mouse event on a table header */
|
||||
let currentHeader;
|
||||
|
||||
/** Current mouse x postion, to track mouse event on a table header */
|
||||
let currentX;
|
||||
|
||||
/**
|
||||
* Flag to temporarily prevent move and resize handles from being shown or hidden.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
let suspendShowHideHandles = false;
|
||||
|
||||
/**
|
||||
* Add handle containers for move and resize handles.
|
||||
*
|
||||
* @param {Element} uiRoot The root element of the quesiton bank UI.
|
||||
* @return {Promise} Resolved after the containers have been added to each column header.
|
||||
*/
|
||||
const addHandleContainers = uiRoot => {
|
||||
return new Promise((resolve) => {
|
||||
const headerContainers = uiRoot.querySelectorAll(SELECTORS.headerContainer);
|
||||
Templates.renderForPromise('qbank_columnsortorder/handle_container', {})
|
||||
.then(({html, js}) => {
|
||||
headerContainers.forEach(container => {
|
||||
Templates.prependNodeContents(container, html, js);
|
||||
});
|
||||
resolve();
|
||||
return headerContainers;
|
||||
}).catch(Notification.exception);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Render move handles in each container.
|
||||
*
|
||||
* This takes a list of the move actions rendered in each column header, and creates a corresponding drag handle for each.
|
||||
*
|
||||
* @param {NodeList} moveActions Menu actions for moving columns.
|
||||
*/
|
||||
const setUpMoveHandles = moveActions => {
|
||||
moveActions.forEach(moveAction => {
|
||||
const header = moveAction.closest('th');
|
||||
header.classList.add('qbank-sortable-column');
|
||||
const handleContainer = header.querySelector(SELECTORS.handleContainer);
|
||||
const context = {
|
||||
action: "move",
|
||||
dragtype: "move",
|
||||
target: '',
|
||||
title: moveAction.title,
|
||||
pixicon: "i/dragdrop",
|
||||
pixcomponent: "core",
|
||||
popup: true
|
||||
};
|
||||
return Templates.renderForPromise('qbank_columnsortorder/action_handle', context)
|
||||
.then(({html, js}) => {
|
||||
Templates.prependNodeContents(handleContainer, html, js);
|
||||
return handleContainer;
|
||||
}).catch(Notification.exception);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Serialise the current column sizes.
|
||||
*
|
||||
* This finds the current width set in each column header's style property, and returns them encoded as a JSON string.
|
||||
*
|
||||
* @param {Element} uiRoot The root element of the quesiton bank UI.
|
||||
* @return {String} JSON array containing a list of objects with column and width properties.
|
||||
*/
|
||||
const serialiseColumnSizes = (uiRoot) => {
|
||||
const columnSizes = [];
|
||||
const tableHeaders = uiRoot.querySelectorAll('th');
|
||||
tableHeaders.forEach(header => {
|
||||
// Only get the width set via style attribute (set by move action).
|
||||
const width = parseInt(header.style.width);
|
||||
if (!width || isNaN(width)) {
|
||||
return;
|
||||
}
|
||||
columnSizes.push({
|
||||
column: header.dataset.columnid,
|
||||
width: width
|
||||
});
|
||||
});
|
||||
return JSON.stringify(columnSizes);
|
||||
};
|
||||
|
||||
/**
|
||||
* Render resize handles in each container.
|
||||
*
|
||||
* This takes a list of the resize actions rendered in each column header, and creates a corresponding drag handle for each.
|
||||
* It also initialises the event handlers for the drag handles and resize modal.
|
||||
*
|
||||
* @param {Element} uiRoot Question bank UI root element.
|
||||
*/
|
||||
const setUpResizeHandles = (uiRoot) => {
|
||||
const resizeActions = uiRoot.querySelectorAll(SELECTORS.resizeAction);
|
||||
resizeActions.forEach(resizeAction => {
|
||||
const headerContainer = resizeAction.closest(SELECTORS.headerContainer);
|
||||
const handleContainer = headerContainer.querySelector(SELECTORS.handleContainer);
|
||||
const context = {
|
||||
action: "resize",
|
||||
target: '',
|
||||
title: resizeAction.title,
|
||||
pixicon: 'i/twoway',
|
||||
pixcomponent: 'core',
|
||||
popup: true
|
||||
};
|
||||
return Templates.renderForPromise('qbank_columnsortorder/action_handle', context)
|
||||
.then(({html, js}) => {
|
||||
Templates.appendNodeContents(handleContainer, html, js);
|
||||
return handleContainer;
|
||||
}).catch(Notification.exception);
|
||||
});
|
||||
|
||||
let moveTracker = false;
|
||||
let currentResizeHandle = null;
|
||||
// Start mouse event on headers.
|
||||
uiRoot.addEventListener('mousedown', e => {
|
||||
currentResizeHandle = e.target.closest(SELECTORS.resizeHandle);
|
||||
// Return if it is not ' resize' button.
|
||||
if (!currentResizeHandle) {
|
||||
return;
|
||||
}
|
||||
// Save current position.
|
||||
currentX = e.pageX;
|
||||
// Find the header.
|
||||
currentHeader = e.target.closest(actions.SELECTORS.sortableColumn);
|
||||
moveTracker = false;
|
||||
suspendShowHideHandles = true;
|
||||
});
|
||||
|
||||
// Resize column as the mouse move.
|
||||
document.addEventListener('mousemove', e => {
|
||||
if (!currentHeader || !currentResizeHandle || currentX === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent text selection as the handle is dragged.
|
||||
document.getSelection().removeAllRanges();
|
||||
|
||||
// Adjust the column width according the amount the handle was dragged.
|
||||
const offset = e.pageX - currentX;
|
||||
currentX = e.pageX;
|
||||
const newWidth = currentHeader.offsetWidth + offset;
|
||||
currentHeader.style.width = newWidth + 'px';
|
||||
moveTracker = true;
|
||||
});
|
||||
|
||||
// Set new size when mouse is up.
|
||||
document.addEventListener('mouseup', () => {
|
||||
if (!currentHeader || !currentResizeHandle || currentX === 0) {
|
||||
return;
|
||||
}
|
||||
if (moveTracker) {
|
||||
// If the mouse moved, we are changing the size by drag, so save the change.
|
||||
repository.setColumnSize(serialiseColumnSizes(uiRoot)).catch(Notification.exception);
|
||||
} else {
|
||||
// If the mouse didn't move, display a modal to change the size using a form.
|
||||
showResizeModal(currentHeader, uiRoot);
|
||||
}
|
||||
currentHeader = null;
|
||||
currentResizeHandle = null;
|
||||
currentX = 0;
|
||||
moveTracker = false;
|
||||
suspendShowHideHandles = false;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Event handler for resize actions in each column header.
|
||||
*
|
||||
* This will listen for a click on any resize action, and activate the corresponding resize modal.
|
||||
*
|
||||
* @param {Element} uiRoot Question bank UI root element.
|
||||
*/
|
||||
const setUpResizeActions = uiRoot => {
|
||||
uiRoot.addEventListener('click', (e) => {
|
||||
const resizeAction = e.target.closest(SELECTORS.resizeAction);
|
||||
if (resizeAction) {
|
||||
e.preventDefault();
|
||||
const currentHeader = resizeAction.closest('th');
|
||||
showResizeModal(currentHeader, uiRoot);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Show a modal containing a number input for changing a column width without click-and-drag.
|
||||
*
|
||||
* @param {Element} currentHeader The header element that is being resized.
|
||||
* @param {Element} uiRoot The question bank UI root element.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
const showResizeModal = async(currentHeader, uiRoot) => {
|
||||
|
||||
const initialWidth = currentHeader.offsetWidth;
|
||||
|
||||
const modal = await ModalFactory.create({
|
||||
title: getString('resizecolumn', 'qbank_columnsortorder', currentHeader.textContent),
|
||||
type: ModalFactory.types.SAVE_CANCEL,
|
||||
body: Templates.render('qbank_columnsortorder/resize_modal', {})
|
||||
});
|
||||
const root = modal.getRoot();
|
||||
root.on(ModalEvents.cancel, () => {
|
||||
currentHeader.style.width = initialWidth + 'px';
|
||||
});
|
||||
root.on(ModalEvents.save, () => {
|
||||
repository.setColumnSize(serialiseColumnSizes(uiRoot)).catch(Notification.exception);
|
||||
});
|
||||
modal.show();
|
||||
|
||||
const body = await modal.bodyPromise;
|
||||
const input = body.get(0).querySelector('input');
|
||||
input.value = initialWidth;
|
||||
|
||||
input.addEventListener('change', e => {
|
||||
const newWidth = e.target.value;
|
||||
currentHeader.style.width = newWidth + 'px';
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Event handler for move actions in each column header.
|
||||
*
|
||||
* This will listen for a click on any move action, pass the click to the corresponding move handle, causing its modal to be shown.
|
||||
*
|
||||
* @param {Element} uiRoot Question bank UI root element.
|
||||
*/
|
||||
const setUpMoveActions = uiRoot => {
|
||||
uiRoot.addEventListener('click', e => {
|
||||
const moveAction = e.target.closest(SELECTORS.moveAction);
|
||||
if (moveAction) {
|
||||
e.preventDefault();
|
||||
const sortableColumn = moveAction.closest(actions.SELECTORS.sortableColumn);
|
||||
const moveHandle = sortableColumn.querySelector(actions.SELECTORS.moveHandler);
|
||||
moveHandle.click();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Event handler for showing and hiding handles when the mouse is over a column header.
|
||||
*
|
||||
* Implementing this behaviour using the :hover CSS pseudoclass is not sufficient, as the mouse may move over the neighbouring
|
||||
* header while dragging, leading to some odd behaviour. This allows us to suspend the show/hide behaviour while a handle is being
|
||||
* dragged, and so keep the active handle visible until the drag is finished.
|
||||
*
|
||||
* @param {Element} uiRoot Question bank UI root element.
|
||||
*/
|
||||
const setupShowHideHandles = uiRoot => {
|
||||
let shownHeader = null;
|
||||
let tableHead = uiRoot.querySelector('thead');
|
||||
uiRoot.addEventListener('mouseover', e => {
|
||||
if (suspendShowHideHandles) {
|
||||
return;
|
||||
}
|
||||
const header = e.target.closest(actions.SELECTORS.sortableColumn);
|
||||
if (!header && !shownHeader) {
|
||||
return;
|
||||
}
|
||||
if (!header || header !== shownHeader) {
|
||||
tableHead.querySelector('.show-handles')?.classList.remove('show-handles');
|
||||
shownHeader = header;
|
||||
if (header) {
|
||||
header.classList.add('show-handles');
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Event handler for sortable list DROP event.
|
||||
*
|
||||
* Find all table cells corresponding to the column of the dropped header, and move them to the new position.
|
||||
*
|
||||
* @param {Event} event
|
||||
*/
|
||||
const reorderColumns = event => {
|
||||
// Current header.
|
||||
const header = event.target;
|
||||
// Find the previous sibling of the header, which will be used when moving columns.
|
||||
const insertAfter = header.previousElementSibling;
|
||||
// Move columns.
|
||||
const uiRoot = document.querySelector(SELECTORS.uiRoot);
|
||||
const columns = uiRoot.querySelectorAll(SELECTORS.tableColumn(header.dataset.columnid));
|
||||
columns.forEach(column => {
|
||||
const row = column.parentElement;
|
||||
if (insertAfter) {
|
||||
// Find the column to insert after.
|
||||
const insertAfterColumn = row.querySelector(SELECTORS.tableColumn(insertAfter.dataset.columnid));
|
||||
// Insert the column.
|
||||
insertAfterColumn.after(column);
|
||||
} else {
|
||||
// Insert as the first child (first column in the table).
|
||||
row.insertBefore(column, row.firstChild);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize module
|
||||
*
|
||||
* Add containers for the drag handles to each column header, then render handles, enable show/hide behaviour, set up drag/drop
|
||||
* column sorting, then enable the move and resize modals to be triggered from menu actions.
|
||||
*/
|
||||
export const init = async() => {
|
||||
const uiRoot = document.querySelector('.questionbankwindow');
|
||||
await addHandleContainers(uiRoot);
|
||||
setUpMoveHandles(uiRoot.querySelectorAll(SELECTORS.moveAction));
|
||||
setUpResizeHandles(uiRoot);
|
||||
setupShowHideHandles(uiRoot);
|
||||
const sortableColumns = actions.setupSortableLists(uiRoot.querySelector(actions.SELECTORS.columnList));
|
||||
sortableColumns.on(SortableList.EVENTS.DROP, reorderColumns);
|
||||
sortableColumns.on(SortableList.EVENTS.DRAGSTART, () => {
|
||||
suspendShowHideHandles = true;
|
||||
});
|
||||
sortableColumns.on(SortableList.EVENTS.DRAGEND, () => {
|
||||
suspendShowHideHandles = false;
|
||||
});
|
||||
setUpMoveActions(uiRoot);
|
||||
setUpResizeActions(uiRoot);
|
||||
};
|
@ -67,9 +67,22 @@ class column_manager extends column_manager_base {
|
||||
*/
|
||||
public function __construct(bool $globalsettings = false) {
|
||||
$this->columnorder = $this->setup_property('enabledcol', $globalsettings);
|
||||
if (empty($this->columnorder)) {
|
||||
$this->columnorder = [
|
||||
'core_question\local\bank\checkbox_column' . column_base::ID_SEPARATOR . 'checkbox_column',
|
||||
'qbank_viewquestiontype\question_type_column' . column_base::ID_SEPARATOR . 'question_type_column',
|
||||
'qbank_viewquestionname\question_name_idnumber_tags_column' . column_base::ID_SEPARATOR .
|
||||
'question_name_idnumber_tags_column',
|
||||
'core_question\local\bank\edit_menu_column' . column_base::ID_SEPARATOR . 'edit_menu_column',
|
||||
'qbank_editquestion\question_status_column' . column_base::ID_SEPARATOR . 'question_status_column',
|
||||
'qbank_history\version_number_column' . column_base::ID_SEPARATOR . 'version_number_column',
|
||||
'qbank_viewcreator\creator_name_column' . column_base::ID_SEPARATOR . 'creator_name_column',
|
||||
'qbank_comment\comment_count_column' . column_base::ID_SEPARATOR . 'comment_count_column',
|
||||
];
|
||||
}
|
||||
$this->hiddencolumns = $this->setup_property('hiddencols', $globalsettings);
|
||||
$this->colsize = $this->setup_property('colsize', $globalsettings, 'json');
|
||||
$this->disabledcolumns = $this->setup_property('disabledcol', $globalsettings);
|
||||
$this->disabledcolumns = $this->setup_property('disabledcol', true); // No user preference for disabledcol.
|
||||
|
||||
if ($this->columnorder) {
|
||||
$this->columnorder = array_flip($this->columnorder);
|
||||
@ -157,9 +170,16 @@ class column_manager extends column_manager_base {
|
||||
$course = (object) ['id' => 0];
|
||||
$context = context_system::instance();
|
||||
$contexts = new question_edit_contexts($context);
|
||||
$category = question_make_default_categories($contexts->all());
|
||||
$params = ['cat' => $category->id . ',' . $context->id];
|
||||
// Dummy call to get the objects without error.
|
||||
$questionbank = new preview_view($contexts, new moodle_url('/question/bank/columnsortorder/sortcolumns.php'), $course,
|
||||
null);
|
||||
$questionbank = new preview_view(
|
||||
$contexts,
|
||||
new moodle_url('/question/bank/columnsortorder/sortcolumns.php'),
|
||||
$course,
|
||||
null,
|
||||
$params
|
||||
);
|
||||
return $questionbank;
|
||||
}
|
||||
|
||||
@ -174,12 +194,11 @@ class column_manager extends column_manager_base {
|
||||
if ($column->get_name() === 'checkbox') {
|
||||
continue;
|
||||
}
|
||||
$classelements = explode('\\', $key);
|
||||
$columns[] = (object) [
|
||||
'class' => get_class($column),
|
||||
'name' => $column->get_title(),
|
||||
'colname' => end($classelements),
|
||||
'id' => implode(self::ID_SEPARATOR, [$column::class, $column->get_column_name()]),
|
||||
'colname' => $column->get_column_name(),
|
||||
'id' => $column->get_column_id(),
|
||||
];
|
||||
}
|
||||
return $columns;
|
||||
@ -194,9 +213,9 @@ class column_manager extends column_manager_base {
|
||||
$disabled = [];
|
||||
if ($this->disabledcolumns) {
|
||||
foreach (array_keys($this->disabledcolumns) as $column) {
|
||||
[$classname, $columnname] = explode(self::ID_SEPARATOR, $column);
|
||||
[$classname, $columnname] = explode(column_base::ID_SEPARATOR, $column, 2);
|
||||
$columnobject = $classname::from_column_name($this->get_questionbank(), $columnname);
|
||||
$disabled[] = (object) [
|
||||
$disabled[$column] = (object) [
|
||||
'disabledname' => $columnobject->get_title(),
|
||||
];
|
||||
}
|
||||
@ -278,7 +297,7 @@ class column_manager extends column_manager_base {
|
||||
/**
|
||||
* Orders columns in the question bank view according to config_plugins table 'qbank_columnsortorder' config.
|
||||
*
|
||||
* @param array $ordertosort Unordered array of columns
|
||||
* @param array $ordertosort Unordered array of columns, [columnname => class]
|
||||
* @return array $properorder|$ordertosort Returns array ordered if 'qbank_columnsortorder' config exists.
|
||||
*/
|
||||
public function get_sorted_columns($ordertosort): array {
|
||||
@ -295,10 +314,13 @@ class column_manager extends column_manager_base {
|
||||
}
|
||||
$properorder = array_merge($columnorder, $ordertosort);
|
||||
// Always have the checkbox at first column position.
|
||||
if (isset($properorder['checkbox_column'])) {
|
||||
$checkboxfirstelement = $properorder['checkbox_column'];
|
||||
unset($properorder['checkbox_column']);
|
||||
$properorder = array_merge(['checkbox_column' => $checkboxfirstelement], $properorder);
|
||||
$checkboxid = 'core_question\local\bank\checkbox_column' . column_base::ID_SEPARATOR . 'checkbox_column';
|
||||
if (isset($properorder[$checkboxid])) {
|
||||
$checkboxfirstelement = $properorder[$checkboxid];
|
||||
unset($properorder[$checkboxid]);
|
||||
$properorder = array_merge([
|
||||
$checkboxid => $checkboxfirstelement
|
||||
], $properorder);
|
||||
}
|
||||
return $properorder;
|
||||
}
|
||||
@ -306,7 +328,7 @@ class column_manager extends column_manager_base {
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an array of columns, set the isvisible attribute according to $this->hiddencolumns.
|
||||
* Given an array of columns, set the isvisible attribute according to $this->hiddencolumns and $this->disabledcolumns.
|
||||
*
|
||||
* @param column_base[] $columns
|
||||
* @return array
|
||||
@ -316,7 +338,9 @@ class column_manager extends column_manager_base {
|
||||
if (!is_object($column)) {
|
||||
continue;
|
||||
}
|
||||
$column->isvisible = !in_array(get_class($column), $this->hiddencolumns);
|
||||
$columnid = $column->get_column_id();
|
||||
|
||||
$column->isvisible = !in_array($columnid, $this->hiddencolumns) && !array_key_exists($columnid, $this->disabledcolumns);
|
||||
}
|
||||
return $columns;
|
||||
}
|
||||
@ -341,16 +365,17 @@ class column_manager extends column_manager_base {
|
||||
*/
|
||||
public function get_hidden_columns(): array {
|
||||
return array_reduce($this->hiddencolumns, function($result, $hiddencolumn) {
|
||||
$result[$hiddencolumn] = (new $hiddencolumn($this->get_questionbank()))->get_title();
|
||||
[$columnclass, $columnname] = explode(column_base::ID_SEPARATOR, $hiddencolumn, 2);
|
||||
$result[$hiddencolumn] = $columnclass::from_column_name($this->get_questionbank(), $columnname)->get_title();
|
||||
return $result;
|
||||
}, []);
|
||||
}
|
||||
|
||||
public function get_column_width(column_base $column): string {
|
||||
$colsizemap = $this->get_colsize_map();
|
||||
$columnclass = get_class($column);
|
||||
if (array_key_exists($columnclass, $colsizemap)) {
|
||||
return $colsizemap[$columnclass] . 'px';
|
||||
$columnid = $column->get_column_id();
|
||||
if (array_key_exists($columnid, $colsizemap)) {
|
||||
return $colsizemap[$columnid] . 'px';
|
||||
}
|
||||
return parent::get_column_width($column);
|
||||
}
|
||||
|
79
question/bank/columnsortorder/classes/external/set_column_size.php
vendored
Normal file
79
question/bank/columnsortorder/classes/external/set_column_size.php
vendored
Normal file
@ -0,0 +1,79 @@
|
||||
<?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 qbank_columnsortorder\external;
|
||||
|
||||
use context_system;
|
||||
use core_external\external_api;
|
||||
use core_external\external_function_parameters;
|
||||
use core_external\external_value;
|
||||
use qbank_columnsortorder\column_manager;
|
||||
|
||||
/**
|
||||
* External function for saving column sizes.
|
||||
*
|
||||
* @package qbank_columnsortorder
|
||||
* @copyright 2023 onwards Catalyst IT EU {@link https://catalyst-eu.net}
|
||||
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class set_column_size extends external_api {
|
||||
/**
|
||||
* Returns description of method parameters.
|
||||
*
|
||||
* @return external_function_parameters
|
||||
*/
|
||||
public static function execute_parameters(): external_function_parameters {
|
||||
return new external_function_parameters([
|
||||
'sizes' => new external_value(PARAM_TEXT, 'Size for each column', VALUE_REQUIRED),
|
||||
'global' => new external_value(PARAM_BOOL, 'Set global config setting, rather than user preference',
|
||||
VALUE_DEFAULT, false),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of method result value.
|
||||
*/
|
||||
public static function execute_returns(): void {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set sizes for columns
|
||||
* Save against user preference if component is specified
|
||||
*
|
||||
* @param string $sizes json string representing [column => size].
|
||||
* @param bool $global Set global config setting, rather than user preference
|
||||
*/
|
||||
public static function execute(string $sizes, bool $global = false): void {
|
||||
[
|
||||
'sizes' => $sizes,
|
||||
'global' => $global,
|
||||
]
|
||||
= self::validate_parameters(self::execute_parameters(),
|
||||
[
|
||||
'sizes' => $sizes,
|
||||
'global' => $global,
|
||||
]);
|
||||
|
||||
$context = context_system::instance();
|
||||
self::validate_context($context);
|
||||
if ($global) {
|
||||
require_capability('moodle/site:config', $context);
|
||||
}
|
||||
|
||||
column_manager::set_column_size($sizes, $global);
|
||||
}
|
||||
}
|
83
question/bank/columnsortorder/classes/external/set_hidden_columns.php
vendored
Normal file
83
question/bank/columnsortorder/classes/external/set_hidden_columns.php
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
<?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 qbank_columnsortorder\external;
|
||||
|
||||
use context_system;
|
||||
use core_external\external_api;
|
||||
use core_external\external_function_parameters;
|
||||
use core_external\external_multiple_structure;
|
||||
use core_external\external_value;
|
||||
use qbank_columnsortorder\column_manager;
|
||||
|
||||
/**
|
||||
* External function for saving the list of hidden columns.
|
||||
*
|
||||
* @package qbank_columnsortorder
|
||||
* @copyright 2023 onwards Catalyst IT EU {@link https://catalyst-eu.net}
|
||||
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class set_hidden_columns extends external_api {
|
||||
/**
|
||||
* Returns description of method parameters.
|
||||
*
|
||||
* @return external_function_parameters
|
||||
*/
|
||||
public static function execute_parameters(): external_function_parameters {
|
||||
return new external_function_parameters([
|
||||
'columns' => new external_multiple_structure(
|
||||
new external_value(PARAM_TEXT, 'Plugin name for the hidden column', VALUE_REQUIRED)
|
||||
),
|
||||
'global' => new external_value(PARAM_BOOL, 'Set global config setting, rather than user preference',
|
||||
VALUE_DEFAULT, false),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of method result value.
|
||||
*
|
||||
*/
|
||||
public static function execute_returns(): void {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set hidden columns
|
||||
* Save against user preference if specified
|
||||
*
|
||||
* @param array $columns list of hidden columns.
|
||||
* @param bool $global Set global config setting, rather than user preference
|
||||
*/
|
||||
public static function execute(array $columns, bool $global = false): void {
|
||||
[
|
||||
'columns' => $columns,
|
||||
'global' => $global,
|
||||
]
|
||||
= self::validate_parameters(self::execute_parameters(),
|
||||
[
|
||||
'columns' => $columns,
|
||||
'global' => $global,
|
||||
]);
|
||||
|
||||
$context = context_system::instance();
|
||||
self::validate_context($context);
|
||||
if ($global) {
|
||||
require_capability('moodle/site:config', $context);
|
||||
}
|
||||
|
||||
column_manager::set_hidden_columns($columns, $global);
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
<?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 qbank_columnsortorder\local\bank;
|
||||
|
||||
use core_question\local\bank\column_action_base;
|
||||
use core_question\local\bank\column_base;
|
||||
|
||||
/**
|
||||
* Move a column
|
||||
*
|
||||
* This will add an action menu item which will be enhanced by javascript in user_actions.js to show the move column modal for the
|
||||
* current column when clicked.
|
||||
*
|
||||
* @package qbank_columnsortorder
|
||||
* @copyright 2023 onwards Catalyst IT EU {@link https://catalyst-eu.net}
|
||||
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class column_action_move extends column_action_base {
|
||||
|
||||
/** @var string Label for the Move action. */
|
||||
protected string $move;
|
||||
|
||||
protected function init(): void {
|
||||
$this->move = get_string('move');
|
||||
}
|
||||
|
||||
public function get_action_menu_link(column_base $column): ?\action_menu_link {
|
||||
return new \action_menu_link_secondary(
|
||||
new \moodle_url('/question/edit.php'),
|
||||
null,
|
||||
$this->move,
|
||||
[
|
||||
'title' => get_string('movecolumn', 'qbank_columnsortorder', $column->get_title()),
|
||||
'data-action' => 'move',
|
||||
'data-column' => get_class($column),
|
||||
]);
|
||||
}
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
<?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 qbank_columnsortorder\local\bank;
|
||||
|
||||
use core_question\local\bank\column_action_base;
|
||||
use core_question\local\bank\column_base;
|
||||
|
||||
/**
|
||||
* Remove a column
|
||||
*
|
||||
* This action will display a link that will set the current column as hidden, then redirect back the current page.
|
||||
*
|
||||
* @package qbank_columnsortorder
|
||||
* @copyright 2023 onwards Catalyst IT EU {@link https://catalyst-eu.net}
|
||||
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class column_action_remove extends column_action_base {
|
||||
|
||||
/** @var bool True if we are changing global config, false for user preferences. */
|
||||
protected bool $global;
|
||||
|
||||
/** @var string Label for the Remove action. */
|
||||
protected string $remove;
|
||||
|
||||
protected function init(): void {
|
||||
$this->global = false;
|
||||
$this->remove = get_string('remove');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the $global property to indicate whether we are changing global config.
|
||||
*
|
||||
* This action is used on both the user and admin screens, so requires this additional method.
|
||||
*
|
||||
* @param bool $global
|
||||
* @return void
|
||||
*/
|
||||
public function set_global(bool $global): void {
|
||||
$this->global = $global;
|
||||
}
|
||||
|
||||
public function get_action_menu_link(column_base $column): ?\action_menu_link {
|
||||
$actionurl = new \moodle_url('/question/bank/columnsortorder/actions.php', [
|
||||
'column' => $column->get_column_id(),
|
||||
'action' => 'remove',
|
||||
'sesskey' => sesskey(),
|
||||
'returnurl' => $this->qbank->returnurl,
|
||||
]);
|
||||
if ($this->global) {
|
||||
$actionurl->param('global', $this->global);
|
||||
}
|
||||
return new \action_menu_link_secondary(
|
||||
$actionurl,
|
||||
null,
|
||||
$this->remove,
|
||||
[
|
||||
'class' => 'action-link',
|
||||
'title' => get_string('removecolumn', 'qbank_columnsortorder', $column->get_title()),
|
||||
'data-action' => 'remove',
|
||||
'data-column' => $column->get_column_id(),
|
||||
]);
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
<?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 qbank_columnsortorder\local\bank;
|
||||
|
||||
use core_question\local\bank\column_action_base;
|
||||
use core_question\local\bank\column_base;
|
||||
|
||||
/**
|
||||
* Resize a column
|
||||
*
|
||||
* This will add an action menu item which will be enhanced by javascript in user_actions.js to show the resize column modal for the
|
||||
* current column when clicked.
|
||||
*
|
||||
* @package qbank_columnsortorder
|
||||
* @copyright 2023 onwards Catalyst IT EU {@link https://catalyst-eu.net}
|
||||
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class column_action_resize extends column_action_base {
|
||||
|
||||
/** @var string Label for the resize action. */
|
||||
protected string $resize;
|
||||
|
||||
protected function init(): void {
|
||||
$this->resize = get_string('resize', 'qbank_columnsortorder');
|
||||
}
|
||||
|
||||
public function get_action_menu_link(column_base $column): ?\action_menu_link {
|
||||
return new \action_menu_link_secondary(
|
||||
new \moodle_url('/question/edit.php'),
|
||||
null,
|
||||
$this->resize,
|
||||
[
|
||||
'title' => get_string('resizecolumn', 'qbank_columnsortorder', $column->get_title()),
|
||||
'data-action' => 'resize',
|
||||
'data-column' => get_class($column),
|
||||
]);
|
||||
}
|
||||
}
|
@ -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 qbank_columnsortorder\local\bank;
|
||||
|
||||
use core_question\local\bank\view;
|
||||
use qbank_columnsortorder\column_manager;
|
||||
|
||||
/**
|
||||
* Custom view for displaying a preview of the question bank
|
||||
*
|
||||
* @package qbank_columnsortorder
|
||||
* @copyright 2023 onwards Catalyst IT EU {@link https://catalyst-eu.net}
|
||||
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class preview_view extends view {
|
||||
|
||||
/**
|
||||
* Use global settings for the column manager.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function init_column_manager(): void {
|
||||
$this->columnmanager = new column_manager(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the table row with the preview data for each column.
|
||||
*
|
||||
* @param \stdClass $question
|
||||
* @param int $rowcount
|
||||
*/
|
||||
public function print_table_row($question, $rowcount): void {
|
||||
$rowclasses = implode(' ', $this->get_row_classes($question, $rowcount));
|
||||
$attributes = [];
|
||||
if ($rowclasses) {
|
||||
$attributes['class'] = $rowclasses;
|
||||
}
|
||||
echo \html_writer::start_tag('tr', $attributes);
|
||||
foreach ($this->visiblecolumns as $column) {
|
||||
$column->display_preview($question, $rowclasses);
|
||||
}
|
||||
echo \html_writer::end_tag('tr');
|
||||
foreach ($this->extrarows as $row) {
|
||||
$row->display_preview($question, $rowclasses);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a dummy question containing valid data for the default question fields.
|
||||
*
|
||||
* @return \stdClass
|
||||
*/
|
||||
protected function get_dummy_question(): \stdClass {
|
||||
return (object)[
|
||||
'id' => 1,
|
||||
'qtype' => 'truefalse',
|
||||
'createdby' => 2,
|
||||
'categoryid' => 1,
|
||||
'contextid' => 1,
|
||||
'status' => 'ready',
|
||||
'version' => 1,
|
||||
'versionid' => 1,
|
||||
'questionbankentryid' => 1,
|
||||
'name' => 'Lorem ipsum',
|
||||
'idnumber' => 123,
|
||||
'creatorfirstname' => 'Admin',
|
||||
'creatorlastname' => 'User',
|
||||
'timecreated' => 1691157311,
|
||||
'modifierfirstname' => 'Admin',
|
||||
'modifierlastname' => 'User',
|
||||
'timemodified' => 1691157311,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a preview of the question bank table with a single dummy question.
|
||||
*
|
||||
* @return string An HTML table containing the column headings and a single question row.
|
||||
*/
|
||||
public function get_preview(): string {
|
||||
ob_start();
|
||||
$this->display_questions([$this->get_dummy_question()]);
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
78
question/bank/columnsortorder/classes/output/add_column.php
Normal file
78
question/bank/columnsortorder/classes/output/add_column.php
Normal file
@ -0,0 +1,78 @@
|
||||
<?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 qbank_columnsortorder\output;
|
||||
|
||||
use core_reportbuilder\local\models\column;
|
||||
use qbank_columnsortorder\column_manager;
|
||||
use moodle_url;
|
||||
use renderer_base;
|
||||
|
||||
/**
|
||||
* Renderable for the "add column" dropdown list
|
||||
*
|
||||
* @package qbank_columnsortorder
|
||||
* @copyright 2023 onwards Catalyst IT EU {@link https://catalyst-eu.net}
|
||||
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class add_column implements \renderable, \templatable {
|
||||
|
||||
/** @var column_manager The column manager for getting the list of hidden columns. */
|
||||
protected column_manager $columnmanager;
|
||||
|
||||
/** @var moodle_url The current page URL to redirect back to. */
|
||||
protected moodle_url $returnurl;
|
||||
|
||||
/** @var bool True if we are changing global config, false for user preferences. */
|
||||
protected bool $global;
|
||||
|
||||
/**
|
||||
* Store arguments for generating template context.
|
||||
*
|
||||
* @param column_manager $columnmanager
|
||||
* @param moodle_url $returnurl
|
||||
* @param bool $global
|
||||
*/
|
||||
public function __construct(column_manager $columnmanager, moodle_url $returnurl, bool $global = false) {
|
||||
$this->columnmanager = $columnmanager;
|
||||
$this->returnurl = $returnurl;
|
||||
$this->global = $global;
|
||||
}
|
||||
|
||||
public function export_for_template(renderer_base $output): array {
|
||||
$hiddencolumns = [];
|
||||
foreach ($this->columnmanager->get_hidden_columns() as $class => $name) {
|
||||
$addurl = new moodle_url('/question/bank/columnsortorder/actions.php', [
|
||||
'action' => 'add',
|
||||
'global' => $this->global,
|
||||
'column' => $class,
|
||||
'sesskey' => sesskey(),
|
||||
'returnurl' => $this->returnurl,
|
||||
]);
|
||||
$hiddencolumns[] = [
|
||||
'name' => $name,
|
||||
'addurl' => $addurl->out(false),
|
||||
'column' => $class,
|
||||
'addtext' => get_string('addcolumn', 'qbank_columnsortorder', $name),
|
||||
];
|
||||
}
|
||||
return [
|
||||
'hashiddencolumns' => !empty($hiddencolumns),
|
||||
'hiddencolumns' => $hiddencolumns,
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
<?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 qbank_columnsortorder\output;
|
||||
|
||||
use moodle_url;
|
||||
use templatable;
|
||||
use renderable;
|
||||
use qbank_columnsortorder\column_manager;
|
||||
|
||||
/**
|
||||
* Renderable for the question bank preview.
|
||||
*
|
||||
* This takes the HTML for a question bank preview, and displays in a page with a link to return to the admin screen.
|
||||
*
|
||||
* @package qbank_columnsortorder
|
||||
* @copyright 2023 onwards Catalyst IT EU {@link https://catalyst-eu.net}
|
||||
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class column_sort_preview implements templatable, renderable {
|
||||
|
||||
/** @var string Rendered preview HTML. */
|
||||
protected string $preview;
|
||||
|
||||
/**
|
||||
* Store rendered preview for template context.
|
||||
*
|
||||
* @param string $preview
|
||||
*/
|
||||
public function __construct(string $preview) {
|
||||
$this->preview = $preview;
|
||||
}
|
||||
|
||||
public function export_for_template(\renderer_base $output): array {
|
||||
$context = [
|
||||
'backurl' => new moodle_url('/question/bank/columnsortorder/sortcolumns.php'),
|
||||
'preview' => $this->preview,
|
||||
];
|
||||
return $context;
|
||||
}
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
<?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 qbank_columnsortorder\output;
|
||||
|
||||
use core_question\local\bank\column_base;
|
||||
use qbank_columnsortorder\local\bank\column_action_remove;
|
||||
use moodle_url;
|
||||
use qbank_columnsortorder\column_manager;
|
||||
use renderable;
|
||||
use templatable;
|
||||
|
||||
/**
|
||||
* Renderable for the column sort admin UI.
|
||||
*
|
||||
* Displays a list of the currently enabled columns and allows them to be sorted, hidden, and resized.
|
||||
*
|
||||
* @package qbank_columnsortorder
|
||||
* @copyright 2023 onwards Catalyst IT EU {@link https://catalyst-eu.net}
|
||||
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class column_sort_ui implements templatable, renderable {
|
||||
|
||||
/**
|
||||
* @var int The minimum custom width for a column.
|
||||
*/
|
||||
const MIN_COLUMN_WIDTH = 10;
|
||||
|
||||
public function export_for_template(\renderer_base $output): array {
|
||||
$columnmanager = new column_manager(true);
|
||||
$enabledcolumns = $columnmanager->get_columns();
|
||||
$disabledcolumns = $columnmanager->get_disabled_columns();
|
||||
$columnsizes = $columnmanager->get_colsize_map();
|
||||
$qbank = $columnmanager->get_questionbank();
|
||||
$returnurl = new moodle_url('/question/bank/columnsortorder/sortcolumns.php');
|
||||
$params = [];
|
||||
$params['formaction'] = new moodle_url('/question/bank/columnsortorder/actions.php');
|
||||
$params['sesskey'] = sesskey();
|
||||
$params['disabled'] = $disabledcolumns;
|
||||
$params['contextid'] = \context_system::instance()->id;
|
||||
$params['minwidth'] = self::MIN_COLUMN_WIDTH;
|
||||
foreach ($enabledcolumns as $column) {
|
||||
if (in_array($column->id, $columnmanager->hiddencolumns) || array_key_exists($column->id, $disabledcolumns)) {
|
||||
continue;
|
||||
}
|
||||
$name = $column->name;
|
||||
$colname = get_string('qbankcolumnname', 'qbank_columnsortorder', $column->colname);
|
||||
|
||||
$removeaction = new column_action_remove($qbank);
|
||||
$removeaction->set_global(true);
|
||||
$actionmenu = new \action_menu([
|
||||
$removeaction->get_action_menu_link($column->class::from_column_name($qbank, $column->colname)),
|
||||
]);
|
||||
$params['names'][] = [
|
||||
'name' => $name,
|
||||
'colname' => $colname,
|
||||
'class' => $column->class,
|
||||
'width' => $columnsizes[$column->id] ?? null,
|
||||
'widthlabel' => get_string('width', 'qbank_columnsortorder', $name),
|
||||
'actionmenu' => $actionmenu->export_for_template($output),
|
||||
'columnid' => $column->id,
|
||||
'escapedid' => str_replace('\\', '__', $column->id),
|
||||
];
|
||||
}
|
||||
|
||||
$params['disabled'] = array_values($disabledcolumns);
|
||||
$params['columnsdisabled'] = !empty($params['disabled']);
|
||||
$addcolumn = new add_column($columnmanager, $returnurl);
|
||||
$params['addcolumn'] = $addcolumn->export_for_template($output);
|
||||
$resetcolums = new reset_columns($returnurl);
|
||||
$params['resetcolumns'] = $resetcolums->export_for_template($output);
|
||||
$params['extraclasses'] = 'pr-1';
|
||||
$urltoredirect = new moodle_url('/admin/settings.php', ['section' => 'manageqbanks']);
|
||||
|
||||
$params['urltomanageqbanks'] = get_string('qbankgotomanageqbanks', 'qbank_columnsortorder', $urltoredirect->out());
|
||||
$params['previewurl'] = new moodle_url('/question/bank/columnsortorder/sortcolumns.php', [
|
||||
'preview' => true
|
||||
]);
|
||||
return $params;
|
||||
}
|
||||
}
|
37
question/bank/columnsortorder/classes/output/fragment.php
Normal file
37
question/bank/columnsortorder/classes/output/fragment.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?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 qbank_columnsortorder\output;
|
||||
|
||||
/**
|
||||
* Output fragments for the column sort order interface
|
||||
*
|
||||
* @package qbank_columnsortorder
|
||||
* @copyright 2023 onwards Catalyst IT EU {@link https://catalyst-eu.net}
|
||||
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class fragment {
|
||||
/**
|
||||
* Render the column sort UI with the current global config.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function column_sort_ui(): string {
|
||||
global $OUTPUT;
|
||||
return $OUTPUT->render(new \qbank_columnsortorder\output\column_sort_ui());
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
<?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 qbank_columnsortorder\output;
|
||||
|
||||
use renderer_base;
|
||||
|
||||
/**
|
||||
* Renderable for resetting customised column settings.
|
||||
*
|
||||
* This will display a link that resets all customised column settings and redirects back to the current page.
|
||||
*
|
||||
* @package qbank_columnsortorder
|
||||
* @copyright 2023 onwards Catalyst IT EU {@link https://catalyst-eu.net}
|
||||
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class reset_columns implements \renderable, \templatable {
|
||||
|
||||
/** @var \moodle_url The current page URL to redirect back to. */
|
||||
protected \moodle_url $returnurl;
|
||||
|
||||
/** @var bool True if we are changing global config, false for user preferences. */
|
||||
protected bool $global;
|
||||
|
||||
/**
|
||||
* Store data for generating the template context.
|
||||
*
|
||||
* @param \moodle_url $returnurl
|
||||
* @param bool $global
|
||||
*/
|
||||
public function __construct(\moodle_url $returnurl, bool $global = false) {
|
||||
$this->returnurl = $returnurl;
|
||||
$this->global = $global;
|
||||
}
|
||||
|
||||
public function export_for_template(renderer_base $output): array {
|
||||
$reseturl = new \moodle_url('/question/bank/columnsortorder/actions.php', [
|
||||
'action' => 'reset',
|
||||
'global' => $this->global,
|
||||
'sesskey' => sesskey(),
|
||||
'returnurl' => $this->returnurl->out(),
|
||||
]);
|
||||
return [
|
||||
'reseturl' => $reseturl->out(false),
|
||||
];
|
||||
}
|
||||
}
|
64
question/bank/columnsortorder/classes/plugin_feature.php
Normal file
64
question/bank/columnsortorder/classes/plugin_feature.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?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 qbank_columnsortorder;
|
||||
|
||||
use core\context;
|
||||
use core_question\local\bank\column_manager_base;
|
||||
use core_question\local\bank\plugin_features_base;
|
||||
use core_question\local\bank\view;
|
||||
use qbank_columnsortorder\output\add_column;
|
||||
use qbank_columnsortorder\output\reset_columns;
|
||||
|
||||
/**
|
||||
* Plugin features for qbank_columnsortorder
|
||||
*
|
||||
* @package qbank_columnsortorder
|
||||
* @copyright 2023 onwards Catalyst IT EU {@link https://catalyst-eu.net}
|
||||
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class plugin_feature extends plugin_features_base {
|
||||
/**
|
||||
* Override the default column manager.
|
||||
*
|
||||
* This will set the column order, size and visibility based on the global settings defined on the admin screen, or on the
|
||||
* current user's preference if they have set one.
|
||||
*
|
||||
* @return ?column_manager_base
|
||||
*/
|
||||
public function get_column_manager() : ?column_manager_base {
|
||||
return new column_manager();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return add and reset column controls.
|
||||
*
|
||||
* @param view $qbank The question bank view.
|
||||
* @param context $context The current context, for permission checks.
|
||||
* @param int $categoryid The current question category ID.
|
||||
* @return \renderable[]
|
||||
*/
|
||||
public function get_question_bank_controls(view $qbank, context $context, int $categoryid) : array {
|
||||
global $PAGE;
|
||||
$PAGE->requires->js_call_amd('qbank_columnsortorder/user_actions', 'init');
|
||||
$returnurl = new \moodle_url($qbank->returnurl);
|
||||
return [
|
||||
200 => new add_column(new column_manager(), $returnurl),
|
||||
300 => new reset_columns($returnurl),
|
||||
];
|
||||
}
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Class defining resuable tests methods for external functions
|
||||
*
|
||||
* @package qbank_columnsortorder
|
||||
* @copyright 2023 Catalyst IT Europe Ltd.
|
||||
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace qbank_columnsortorder\tests;
|
||||
|
||||
/**
|
||||
* Class defining resuable tests methods for external functions
|
||||
*/
|
||||
abstract class external_function_testcase extends \advanced_testcase {
|
||||
|
||||
/**
|
||||
* @var string Fully-qualified external function class to test.
|
||||
*/
|
||||
protected $testclass;
|
||||
|
||||
/**
|
||||
* @var string The name of the setting used to store the data.
|
||||
*/
|
||||
protected $setting;
|
||||
|
||||
/**
|
||||
* @var bool Whether the data is stored as a comma-separated list.
|
||||
*/
|
||||
protected $csv = true;
|
||||
|
||||
/**
|
||||
* A function that returns the data to be passed to the external function.
|
||||
*
|
||||
* The data returned will depend on the testclass.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract protected function generate_test_data(): mixed;
|
||||
|
||||
/**
|
||||
* Test that execute() method sets the correct config setting.
|
||||
*/
|
||||
public function test_execute(): void {
|
||||
$this->resetAfterTest(true);
|
||||
$this->setAdminUser();
|
||||
|
||||
$testdata = $this->generate_test_data();
|
||||
$this->testclass::execute($testdata, true);
|
||||
|
||||
$currentconfig = get_config('qbank_columnsortorder', $this->setting);
|
||||
if ($this->csv) {
|
||||
$currentconfig = explode(',', $currentconfig);
|
||||
}
|
||||
|
||||
$this->assertEqualsCanonicalizing($testdata, $currentconfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that execute() method sets user preference when a component is passed.
|
||||
*/
|
||||
public function test_execute_user(): void {
|
||||
$this->resetAfterTest(true);
|
||||
$user = $this->getDataGenerator()->create_user();
|
||||
$this->setUser($user);
|
||||
|
||||
$testdata = $this->generate_test_data();
|
||||
$this->testclass::execute($testdata);
|
||||
|
||||
$userpreference = get_user_preferences('qbank_columnsortorder_' . $this->setting);
|
||||
if ($this->csv) {
|
||||
$userpreference = explode(',', $userpreference);
|
||||
}
|
||||
|
||||
$this->assertEqualsCanonicalizing($testdata, $userpreference);
|
||||
}
|
||||
}
|
36
question/bank/columnsortorder/lib.php
Normal file
36
question/bank/columnsortorder/lib.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Standard callback functions for qbank_columnsortorder
|
||||
*
|
||||
* This file only exists for defining fragment callbacks. Do not include any other functions here.
|
||||
*
|
||||
* @package qbank_columnsortorder
|
||||
* @copyright 2023 onwards Catalyst IT EU {@link https://catalyst-eu.net}
|
||||
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
/**
|
||||
* Render the column sort UI. {@see \qbank_columnsortorder\output\fragment::column_sort_ui()}
|
||||
*
|
||||
* @param array $args
|
||||
* @return string
|
||||
*/
|
||||
function qbank_columnsortorder_output_fragment_column_sort_ui(array $args): string {
|
||||
return \qbank_columnsortorder\output\fragment::column_sort_ui();
|
||||
}
|
43
question/bank/columnsortorder/styles.css
Normal file
43
question/bank/columnsortorder/styles.css
Normal file
@ -0,0 +1,43 @@
|
||||
#page-admin-question-bank-columnsortorder-sortcolumns .addcolumn {
|
||||
display: inline-block;
|
||||
}
|
||||
.qbank-sortable-column {
|
||||
background-color: white;
|
||||
position: relative;
|
||||
}
|
||||
.jsenabled .qbank-column-list button.savewidths {
|
||||
display: none;
|
||||
}
|
||||
.qbank-sortable-column .qbank_columnsortorder-action-handle {
|
||||
display: none;
|
||||
}
|
||||
.qbank-sortable-column.show-handles .qbank_columnsortorder-action-handle {
|
||||
display: block;
|
||||
}
|
||||
.qbank-sortable-column .handle-container {
|
||||
pointer-events: none; /* Prevent the handle container blocking clicks to elements in the header */
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 40%;
|
||||
z-index: 1;
|
||||
}
|
||||
.qbank_columnsortorder-action-handle {
|
||||
pointer-events: auto; /* Ensure the handles themselves receive clicks */
|
||||
}
|
||||
.qbank_columnsortorder-action-handle.move {
|
||||
margin-left: -21px;
|
||||
width: 16px;
|
||||
}
|
||||
.qbank_columnsortorder-action-handle.resize {
|
||||
cursor: col-resize;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 5px;
|
||||
}
|
||||
.qbank_columnsortorder-action-handle.resize img {
|
||||
/* Prevent the resize handle icon being dragged across the page */
|
||||
pointer-events: none;
|
||||
}
|
||||
.qbank_columnsortorder-action-handle .icon {
|
||||
margin-right: 0;
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
{{!
|
||||
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 qbank_columnsortorder/action_handle
|
||||
|
||||
Render a single action handle for customising a column.
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"action": "move",
|
||||
"target": "",
|
||||
"title": "Move column A",
|
||||
"pixicon": "i/dragdrop",
|
||||
"pixcomponent": "core",
|
||||
"popup": true
|
||||
}
|
||||
}}
|
||||
<span class="qbank_columnsortorder-action-handle {{action}}" tabindex="0" role="button"{{#popup}} aria-haspopup="true"{{/popup}}
|
||||
data-action="{{action}}"
|
||||
data-target="{{target}}"
|
||||
{{#dragtype}}data-drag-type="{{dragtype}}" {{/dragtype}}
|
||||
title="{{title}}">
|
||||
{{#pixicon}}
|
||||
{{#pix}}{{pixicon}}, {{pixcomponent}}{{/pix}}
|
||||
{{/pixicon}}
|
||||
{{#icon}}
|
||||
<i class="fa fa-{{{icon}}} mr-1" aria-hidden="true"></i>
|
||||
{{/icon}}
|
||||
{{#text}}
|
||||
{{text}}
|
||||
{{/text}}
|
||||
</span>
|
57
question/bank/columnsortorder/templates/add_column.mustache
Normal file
57
question/bank/columnsortorder/templates/add_column.mustache
Normal file
@ -0,0 +1,57 @@
|
||||
{{!
|
||||
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 qbank_columnsortorder/add_column
|
||||
|
||||
Add column widget
|
||||
|
||||
Displays a list of currently hidden columns, with links to add them back to the question bank.
|
||||
|
||||
Context variables required for this template:
|
||||
* hiddencolumns - list of currently hidden columns
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"hashiddencolumns": true,
|
||||
"hiddencolumns": [
|
||||
{
|
||||
"name": "Column A",
|
||||
"class": "class_name_A",
|
||||
"addurl": "/question/bank/columnsortorder/actions.php?action=add&column=class_name_A"
|
||||
},
|
||||
{
|
||||
"name": "Column B",
|
||||
"class": "class_name_B",
|
||||
"addurl": "/question/bank/columnsortorder/actions.php?action=add&column=class_name_B"
|
||||
}
|
||||
]
|
||||
}
|
||||
}}
|
||||
{{#hashiddencolumns}}
|
||||
<div class="dropdown addcolumn">
|
||||
<button class="btn btn-outline-dark dropdown-toggle ml-1" data-toggle="dropdown" id="addcolumndropdown" aria-haspopup="true" aria-expanded="false">
|
||||
{{#str}}addcolumns, qbank_columnsortorder{{/str}}
|
||||
</button>
|
||||
<div class="dropdown-menu" aria-labelledby="addcolumndropdown">
|
||||
{{#hiddencolumns}}
|
||||
<a class="dropdown-item action-link" href="{{addurl}}" title="{{addtext}}" data-action="add" data-column="{{column}}">
|
||||
{{name}}
|
||||
</a>
|
||||
{{/hiddencolumns}}
|
||||
</div>
|
||||
</div>
|
||||
{{/hashiddencolumns}}
|
@ -0,0 +1,37 @@
|
||||
{{!
|
||||
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 qbank_columnsortorder/column_sort_preview
|
||||
|
||||
Display a preview of the question bank, with a button to return to the customisation UI.
|
||||
|
||||
Context variables required for this template:
|
||||
* backurl - URL of customisation UI page.
|
||||
* preview - Rendered HTML for a question bank table with the current settings.
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"backurl": "https://example.com/question/bank/columnsortorder/sortcolumns.php",
|
||||
"preview": "<table></table>"
|
||||
}
|
||||
}}
|
||||
<div id="qbank_columnsortorder-{{uniqid}}" class="container">
|
||||
|
||||
<a class="btn btn-primary" href="{{backurl}}">Back</a>
|
||||
|
||||
{{{preview}}}
|
||||
</div>
|
181
question/bank/columnsortorder/templates/column_sort_ui.mustache
Normal file
181
question/bank/columnsortorder/templates/column_sort_ui.mustache
Normal file
@ -0,0 +1,181 @@
|
||||
{{!
|
||||
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 qbank_columnsortorder/column_sort_ui
|
||||
|
||||
Display a list of enable columns with customisation controls, and a list of columns from disabled plugins, with a link to the
|
||||
question bank plugin management screen.
|
||||
|
||||
Context variables required for this template:
|
||||
* contextid - Current context id.
|
||||
* formaction - The URL of the actions controller to submit the form to.
|
||||
* sesskey - The current sesskey.
|
||||
* previewurl - The URL of the question bank preview page.
|
||||
* addcolumn - The context for the qbank_columnsortorder/add_column template.
|
||||
* resetcolumns - The context for the qbank_columnsortorder/reset_columns template.
|
||||
* names - A list of the currently active columns
|
||||
* name - The display name of the column
|
||||
* tiptitle - The tooltip text for the move handle.
|
||||
* colname - The unique class name for the column from the plugin.
|
||||
* escapedclass - The class name with \ replaced by __.
|
||||
* widthlabel - The label text of for this column's width field.
|
||||
* minwidth - The minimum value for the width field.
|
||||
* width - The current value for the width field.
|
||||
* actionmenu - The context for core/action_menu, a list of actions for the column.
|
||||
* columnsdisabled - Are the any columns defined by disabled plugins?
|
||||
* disabled - A list of disabled column names.
|
||||
* disabledname - The disabled column's name.
|
||||
* urltomanageqbanks - Link to the page for managing qbank plugins.
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"contextid": 1,
|
||||
"formaction": "https://example.com/question/bank/columnsortorder/actions.php",
|
||||
"sesskey": "12345abcde",
|
||||
"previewurl": "https://example.com/question/bank/columnsortorder/sortcolumns.php?preview=1",
|
||||
"addcolumn": {
|
||||
"hashiddencolumns": true,
|
||||
"hiddencolumns": [
|
||||
{
|
||||
"name": "Column A",
|
||||
"class": "class_name_A",
|
||||
"addurl": "/question/bank/columnsortorder/actions.php?action=add&column=class_name_A"
|
||||
},
|
||||
{
|
||||
"name": "Column B",
|
||||
"class": "class_name_B",
|
||||
"addurl": "/question/bank/columnsortorder/actions.php?action=add&column=class_name_B"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resetcolumns": {
|
||||
"reseturl": "https://example.com/question/bank/columnsortorder/actions.php?action=reset"
|
||||
},
|
||||
"names": [
|
||||
{
|
||||
"name": "Column A",
|
||||
"tiptitle": "Move Column A",
|
||||
"columnid": "qbank_example\\col_name_A-col_name_A",
|
||||
"escapedid": "qbank_example__col_name_A-col_name_A",
|
||||
"widthlabel": "Width of Column A",
|
||||
"minwidth": "10",
|
||||
"width": ""
|
||||
},
|
||||
{
|
||||
"name": "Column B",
|
||||
"tiptitle": "Move Column B",
|
||||
"columnid": "qbank_example\\col_name_B-col_name_B",
|
||||
"escapedid": "qbank_example__col_name_B-col_name_B",
|
||||
"minwidth": "10",
|
||||
"width": "200"
|
||||
}
|
||||
],
|
||||
"columnsdisabled": true,
|
||||
"disabled": [
|
||||
{
|
||||
"disabledname": "disabled_1"
|
||||
},
|
||||
{
|
||||
"disabledname": "disabled_2"
|
||||
}
|
||||
],
|
||||
"urltomanageqbanks": "<a href=\"https://example.com/admin/manageqbankplugins.php\">Manage qbank plugins</a>"
|
||||
}
|
||||
}}
|
||||
<div id="qbank_columnsortorder-{{uniqid}}" {{!
|
||||
}}class="container" {{!
|
||||
}}data-component="qbank_columnsortorder" {{!
|
||||
}}data-callback="column_sort_ui" {{!
|
||||
}}data-contextid="{{contextid}}">
|
||||
<p>
|
||||
{{#str}}qbanksortdescription, qbank_columnsortorder{{/str}}
|
||||
</p>
|
||||
<form class="has-validation" action="{{formaction}}" method="post">
|
||||
<input type="hidden" name="sesskey" value="{{sesskey}}">{{!
|
||||
}}<div class="d-grid gap-2 d-md-flex justify-content-between mb-2">
|
||||
<div>
|
||||
<a class="btn btn-primary" href="{{previewurl}}">
|
||||
{{#str}}preview{{/str}}
|
||||
</a>
|
||||
{{#addcolumn}}
|
||||
{{>qbank_columnsortorder/add_column}}
|
||||
{{/addcolumn}}
|
||||
</div>
|
||||
{{#resetcolumns}}
|
||||
{{>qbank_columnsortorder/reset_columns}}
|
||||
{{/resetcolumns}}
|
||||
</div>
|
||||
<table class="generaltable table table-fixed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col"></th>
|
||||
<th scope="col">{{#str}}name{{/str}}</th>
|
||||
<th scope="col">{{#str}}plugin{{/str}}</th>
|
||||
<th scope="col" class="w-25">{{#str}}columnwidth, qbank_columnsortorder{{/str}}</th>
|
||||
<th scope="col">{{#str}}action{{/str}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="qbank-column-list">
|
||||
{{#names}}
|
||||
<tr class="qbank-sortable-column" data-pluginname="{{class}}" data-name="{{name}}" data-columnid="{{columnid}}">
|
||||
<td>{{>core/drag_handle}}</td>
|
||||
<td>{{name}}</td>
|
||||
<td>{{colname}}</td>
|
||||
<td>
|
||||
<div class="input-group">
|
||||
<label class="sr-only" for="width_{{escapedid}}">{{widthlabel}}</label>
|
||||
<input id="width_{{escapedid}}" {{!
|
||||
}}class="form-control width-input" {{!
|
||||
}}type="number" {{!
|
||||
}}min="{{minwidth}}" {{!
|
||||
}}name="width[{{escapedid}}]" {{!
|
||||
}}placeholder="{{#str}}auto, qbank_columnsortorder{{/str}}" {{!
|
||||
}}value="{{width}}">
|
||||
<button class="btn btn-sm btn-outline-dark savewidths" type="submit" name="action" value="savewidths">
|
||||
{{#str}}save{{/str}}
|
||||
</button>
|
||||
<div class="invalid-feedback">
|
||||
{{#str}}invalidwidth, qbank_columnsortorder{{/str}}
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>{{#actionmenu}}{{>core/action_menu}}{{/actionmenu}}</td>
|
||||
</tr>
|
||||
{{/names}}
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
<div>
|
||||
{{#columnsdisabled}}
|
||||
{{#str}}qbankcolumnsdisabled, qbank_columnsortorder{{/str}}
|
||||
<br>
|
||||
{{/columnsdisabled}}
|
||||
{{#disabled}}
|
||||
<div class="list-group-item disabled">
|
||||
{{disabledname}}
|
||||
</div>
|
||||
{{/disabled}}
|
||||
</div>
|
||||
<div>
|
||||
{{{urltomanageqbanks}}}
|
||||
</div>
|
||||
{{#js}}
|
||||
require(['qbank_columnsortorder/admin_actions'], function(AdminTable) {
|
||||
AdminTable.init("qbank_columnsortorder-{{uniqid}}");
|
||||
});
|
||||
{{/js}}
|
||||
</div>
|
@ -0,0 +1,27 @@
|
||||
{{!
|
||||
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 qbank_columnsortorder/handle_container
|
||||
|
||||
Container for move/resize handles.
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
}
|
||||
}}
|
||||
<div class="handle-container">
|
||||
</div>
|
@ -0,0 +1,33 @@
|
||||
{{!
|
||||
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 qbank_columnsortorder/reset_columns
|
||||
|
||||
Button to reset question bank column settings to defaults.
|
||||
|
||||
Context variables required for this template:
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
"reseturl": "https://example.com/question/bank/columnsortorder/actions.php?action=reset"
|
||||
}
|
||||
}}
|
||||
<span>
|
||||
<a href="{{reseturl}}" class="btn btn-outline-dark action-link ml-1" data-action="reset">
|
||||
{{#str}}resetcolumns, qbank_columnsortorder{{/str}}
|
||||
</a>
|
||||
</span>
|
@ -0,0 +1,29 @@
|
||||
{{!
|
||||
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 qbank_columnsortorder/resize_modal
|
||||
|
||||
This template renders the content of the resize modal, a number input to set the column width in pixels.
|
||||
|
||||
Example context (json):
|
||||
{
|
||||
}
|
||||
}}
|
||||
<label>
|
||||
{{#str}}columnwidth, qbank_columnsortorder{{/str}}
|
||||
<input name="columnwidth" type="number" value="">
|
||||
</label>
|
101
question/bank/columnsortorder/tests/behat/admin_settings.feature
Normal file
101
question/bank/columnsortorder/tests/behat/admin_settings.feature
Normal file
@ -0,0 +1,101 @@
|
||||
@qbank @qbank_columnsortorder @javascript
|
||||
Feature: Set default question bank column order and size
|
||||
In order to set sensible defaults for the question bank interface
|
||||
As an admin
|
||||
I want to hide, reorder, and resize columns
|
||||
|
||||
Scenario: Admin can reorder question bank columns
|
||||
Given I change the window size to "large"
|
||||
And I log in as "admin"
|
||||
When I navigate to "Plugins > Question bank plugins > Column sort order" in site administration
|
||||
And I drag "Created by" "qbank_columnsortorder > column move handle" and I drop it in "T" "qbank_columnsortorder > column move handle"
|
||||
Then "Created by" "table_row" should appear before "T" "table_row"
|
||||
And I reload the page
|
||||
And "Created by" "table_row" should appear before "T" "table_row"
|
||||
And I follow "Preview"
|
||||
And "Created by" "qbank_columnsortorder > column header" should appear before "T" "qbank_columnsortorder > column header"
|
||||
|
||||
Scenario: Disabling a question bank plugin removes its columns
|
||||
Given I log in as "admin"
|
||||
When I navigate to "Plugins > Question bank plugins > Column sort order" in site administration
|
||||
And I should see "Created by"
|
||||
And I click on "Manage question bank plugins" "link"
|
||||
And I click on "Disable" "link" in the "View creator" "table_row"
|
||||
And I click on "Column sort order" "link"
|
||||
Then "Currently disabled question bank plugins:" "text" should appear before "Created by" "text"
|
||||
And I click on "Manage question bank plugins" "link"
|
||||
And I click on "Enable" "link" in the "View creator" "table_row"
|
||||
And I click on "Column sort order" "link"
|
||||
Then I should not see "Currently disabled question bank plugins:"
|
||||
And I should see "Created by"
|
||||
|
||||
Scenario: Admin can hide a column in site administration page
|
||||
Given I log in as "admin"
|
||||
And I navigate to "Plugins > Question bank plugins > Column sort order" in site administration
|
||||
And "Created by" "table_row" should exist
|
||||
When I click on "Actions menu" "link" in the "Created by" "table_row"
|
||||
And I choose "Remove" in the open action menu
|
||||
Then "Created by" "table_row" should not exist
|
||||
And I reload the page
|
||||
And "Created by" "table_row" should not exist
|
||||
And I follow "Preview"
|
||||
And "Created by" "qbank_columnsortorder > column header" should not exist
|
||||
|
||||
Scenario: Admin can show a column in site administration page
|
||||
Given the following config values are set as admin:
|
||||
| config | value | plugin |
|
||||
| hiddencols | qbank_viewcreator\creator_name_column-creator_name_column | qbank_columnsortorder |
|
||||
And I log in as "admin"
|
||||
And I navigate to "Plugins > Question bank plugins > Column sort order" in site administration
|
||||
And "Created by" "table_row" should not exist
|
||||
When I press "Add columns"
|
||||
And I follow "Created by"
|
||||
Then "Created by" "table_row" should exist
|
||||
And I reload the page
|
||||
And "Created by" "table_row" should exist
|
||||
And I follow "Preview"
|
||||
And "Created by" "qbank_columnsortorder > column header" should exist
|
||||
|
||||
Scenario: Admin can resize a column in site administration page
|
||||
Given I log in as "admin"
|
||||
And I navigate to "Plugins > Question bank plugins > Column sort order" in site administration
|
||||
And the field "Width of 'Question' in pixels" matches value ""
|
||||
When I set the field "Width of 'Question' in pixels" to "400"
|
||||
And I reload the page
|
||||
Then the field "Width of 'Question' in pixels" matches value "400"
|
||||
And I follow "Preview"
|
||||
And the "style" attribute of "Question" "qbank_columnsortorder > column header" should contain "width: 400px"
|
||||
|
||||
Scenario: Custom fields can be reordered, resized, hidden and shown
|
||||
Given I change the window size to "large"
|
||||
And I log in as "admin"
|
||||
And I navigate to "Plugins > Question bank plugins > Question custom fields" in site administration
|
||||
And I press "Add a new category"
|
||||
And I click on "Add a new custom field" "link"
|
||||
And I follow "Checkbox"
|
||||
And I set the following fields to these values:
|
||||
| Name | checkboxcustomcolumn |
|
||||
| Short name | chckcust |
|
||||
And I press "Save changes"
|
||||
And I should see "checkboxcustomcolumn"
|
||||
And I navigate to "Plugins > Question bank plugins > Column sort order" in site administration
|
||||
And "checkboxcustomcolumn" "table_row" should appear after "Comments" "table_row"
|
||||
When I drag "checkboxcustomcolumn" "qbank_columnsortorder > column move handle" and I drop it in "Comments" "qbank_columnsortorder > column move handle"
|
||||
And I set the field "Width of 'checkboxcustomcolumn' in pixels" to "200"
|
||||
And I follow "Preview"
|
||||
And "checkboxcustomcolumn" "qbank_columnsortorder > column header" should appear before "Comments" "qbank_columnsortorder > column header"
|
||||
And the "style" attribute of "checkboxcustomcolumn" "qbank_columnsortorder > column header" should contain "width: 200px"
|
||||
And I follow "Back"
|
||||
And "checkboxcustomcolumn" "table_row" should appear before "Comments" "table_row"
|
||||
And the field "Width of 'checkboxcustomcolumn' in pixels" matches value "200"
|
||||
And I click on "Actions menu" "link" in the "checkboxcustomcolumn" "table_row"
|
||||
And I choose "Remove" in the open action menu
|
||||
And "checkboxcustomcolumn" "table_row" should not exist
|
||||
And I follow "Preview"
|
||||
And "checkboxcustomcolumn" "qbank_columnsortorder > column header" should not exist
|
||||
And I follow "Back"
|
||||
And I press "Add columns"
|
||||
And I follow "checkboxcustomcolumn"
|
||||
And "checkboxcustomcolumn" "table_row" should exist
|
||||
And I follow "Preview"
|
||||
And "checkboxcustomcolumn" "qbank_columnsortorder > column header" should exist
|
@ -0,0 +1,44 @@
|
||||
<?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/>.
|
||||
|
||||
// NOTE: no MOODLE_INTERNAL test here, this file may be required by behat before including /config.php.
|
||||
|
||||
require_once(__DIR__ . '/../../../../../lib/behat/behat_base.php');
|
||||
|
||||
/**
|
||||
* Steps definitions related with the drag and drop header.
|
||||
* @package qbank_columnsortorder
|
||||
* @category test
|
||||
* @copyright 2022 Catalyst IT Australia Pty Ltd
|
||||
* @author Nathan Nguyen <nathannguyen@catalyst-ca.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class behat_qbank_columnsortorder extends behat_base {
|
||||
|
||||
public static function get_exact_named_selectors(): array {
|
||||
return [
|
||||
new behat_component_named_selector('column header', [
|
||||
"//th[contains(@data-name, %locator%)]",
|
||||
]),
|
||||
new behat_component_named_selector('column move handle', [
|
||||
"//*[self::th or self::tr][contains(@data-name, %locator%)]//span[contains(@data-drag-type, 'move')]",
|
||||
]),
|
||||
new behat_component_named_selector('column resize handle', [
|
||||
"//th[contains(@data-name, %locator%)]//span[contains(@data-action, 'resize')]",
|
||||
]),
|
||||
];
|
||||
}
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
@qbank @qbank_columnsortorder @javascript
|
||||
Feature: An plugin column can be reordered and displayed in the question bank view.
|
||||
In order to reorganise the question bank view columns
|
||||
As an admin
|
||||
I need to be able to reorder them
|
||||
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | format |
|
||||
| Course 1 | C1 | weeks |
|
||||
And the following "activity" exists:
|
||||
| activity | quiz |
|
||||
| course | C1 |
|
||||
| name | Test quiz Q001 |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And the following "question category" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | Test quiz Q001 | Question category 1 |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | user | questiontext | idnumber |
|
||||
| Question category 1 | essay | Test question to be seen | teacher1 | Write about whatever you want | idnumber1 |
|
||||
|
||||
Scenario: Teacher can see proper view
|
||||
Given I am on the "Test quiz Q001" "mod_quiz > question bank" page logged in as "teacher1"
|
||||
When I apply question bank filter "Category" with value "Question category 1"
|
||||
And I should see "Test question to be seen"
|
||||
Then I should see "Teacher 1"
|
||||
|
||||
Scenario: Reordering question bank columns
|
||||
Given I log in as "admin"
|
||||
When I navigate to "Plugins > Question bank plugins > Column sort order" in site administration
|
||||
And I drag "Created by (creator_name_column)" "text" and I drop it in "T (question_type_column)" "text"
|
||||
And I am on the "Test quiz Q001" "mod_quiz > question bank" page logged in as "teacher1"
|
||||
And I apply question bank filter "Category" with value "Question category 1"
|
||||
Then ".creatorname" "css_element" should appear before ".qtype" "css_element"
|
||||
|
||||
Scenario: Disabling and enabling column display is proper
|
||||
Given I log in as "admin"
|
||||
When I navigate to "Plugins > Question bank plugins > Column sort order" in site administration
|
||||
And I should see "Created by (creator_name_column)"
|
||||
And I click on "Manage question bank plugins" "link"
|
||||
And I click on "Disable" "link" in the "View creator" "table_row"
|
||||
And I click on "Column sort order" "link"
|
||||
Then "Currently disabled question bank plugins:" "text" should appear before "Created by" "text"
|
||||
And I should not see "Created by (creator_name_column)"
|
||||
And I click on "Manage question bank plugins" "link"
|
||||
And I click on "Enable" "link" in the "View creator" "table_row"
|
||||
And I click on "Column sort order" "link"
|
||||
Then I should not see "Currently disabled question bank plugins:"
|
||||
And I should see "Created by (creator_name_column)"
|
||||
|
||||
Scenario: Custom fields are reorderable
|
||||
Given I log in as "admin"
|
||||
When I navigate to "Plugins > Question bank plugins > Question custom fields" in site administration
|
||||
And I press "Add a new category"
|
||||
And I click on "Add a new custom field" "link"
|
||||
And I follow "Checkbox"
|
||||
And I set the following fields to these values:
|
||||
| Name | checkboxcustomcolumn |
|
||||
| Short name | chckcust |
|
||||
And I press "Save changes"
|
||||
Then I should see "checkboxcustomcolumn"
|
||||
And I navigate to "Plugins > Question bank plugins > Column sort order" in site administration
|
||||
And I should see "checkboxcustomcolumn"
|
||||
And I change the window size to "large"
|
||||
And I drag "checkboxcustomcolumn" "text" and I drop it in "T (question_type_column)" "text"
|
||||
Then "checkboxcustomcolumn" "text" should appear before "T (question_type_column)" "text"
|
||||
And I click on "Manage question bank plugins" "link"
|
||||
And I click on "Disable" "link" in the "Question custom fields" "table_row"
|
||||
And I click on "Column sort order" "link"
|
||||
Then "Currently disabled question bank plugins:" "text" should appear before "chckcust" "text"
|
||||
And I click on "Manage question bank plugins" "link"
|
||||
And I click on "Enable" "link" in the "Question custom fields" "table_row"
|
||||
And I click on "Column sort order" "link"
|
||||
Then I should not see "Currently disabled question bank plugins:"
|
||||
And I should see "checkboxcustomcolumn"
|
||||
|
||||
Scenario: Reordering with disabled columns
|
||||
When I log in as "admin"
|
||||
And I navigate to "Plugins > Question bank plugins > Manage question bank plugins" in site administration
|
||||
And I click on "Disable" "link" in the "Question statistics" "table_row"
|
||||
And I click on "Enable" "link" in the "Question statistics" "table_row"
|
||||
And I click on "Disable" "link" in the "Question statistics" "table_row"
|
||||
And I am on the "Course 1" "core_question > course question bank" page
|
||||
Then I should see "Question bank"
|
||||
And "Create a new question" "button" should exist
|
||||
# Really, we are just checking the question bank displayed without errors.
|
127
question/bank/columnsortorder/tests/behat/question_bank.feature
Normal file
127
question/bank/columnsortorder/tests/behat/question_bank.feature
Normal file
@ -0,0 +1,127 @@
|
||||
@qbank @qbank_columnsortorder @javascript
|
||||
Feature: Set question bank column order and size
|
||||
In order customise my view of the question bank
|
||||
As a teacher
|
||||
I want to hide, reorder, and resize columns
|
||||
|
||||
Background:
|
||||
Given the following "users" exist:
|
||||
| username | firstname | lastname | email |
|
||||
| teacher1 | Teacher | 1 | teacher1@example.com |
|
||||
And the following "courses" exist:
|
||||
| fullname | shortname | format |
|
||||
| Course 1 | C1 | weeks |
|
||||
And the following "activity" exists:
|
||||
| activity | quiz |
|
||||
| course | C1 |
|
||||
| name | Test quiz Q001 |
|
||||
And the following "course enrolments" exist:
|
||||
| user | course | role |
|
||||
| teacher1 | C1 | editingteacher |
|
||||
And the following "question category" exist:
|
||||
| contextlevel | reference | name |
|
||||
| Activity module | Test quiz Q001 | Question category 1 |
|
||||
And the following "questions" exist:
|
||||
| questioncategory | qtype | name | user | questiontext | idnumber |
|
||||
| Question category 1 | essay | Test question to be seen | teacher1 | Write about whatever you want | idnumber1 |
|
||||
And the following config values are set as admin:
|
||||
| config | value | plugin |
|
||||
| hiddencols | qbank_usage\question_last_used_column-question_last_used_column | qbank_columnsortorder |
|
||||
| enabledcol | qbank_comment\comment_count_column-comment_count_column,qbank_viewquestionname\question_name_idnumber_tags_column-question_name_idnumber_tags_column,core_question\local\bank\edit_menu_column-edit_menu_column,qbank_editquestion\question_status_column-question_status_column,qbank_history\version_number_column-version_number_column,qbank_statistics\columns\discrimination_index:discrimination_index,qbank_statistics\columns\facility_index:facility_index,qbank_statistics\columns\discriminative_efficiency:discriminative_efficiency,qbank_usage\question_usage_column-question_usage_column,qbank_usage\question_last_used_column-question_last_used_column,qbank_viewcreator\creator_name_column-creator_name_column,qbank_viewcreator\modifier_name_column-modifier_name_column,qbank_viewquestiontype\question_type_column-question_type_column | qbank_columnsortorder |
|
||||
| colsize | [{"column":"qbank_comment\\comment_count_column-comment_count_column","width":"20"},{"column":"qbank_viewquestionname\\question_name_idnumber_tags_column-question_name_idnumber_tags_column","width":"300"},{"column":"qbank_editquestion\\question_status_column-question_status_column","width":"20"},{"column":"qbank_history\\version_number_column-version_number_column","width":"20"},{"column":"qbank_statistics\\columns\\discrimination_index:discrimination_index","width":"20"},{"column":"qbank_statistics\\columns\\facility_index:facility_index","width":"20"},{"column":"qbank_statistics\\columns\\discriminative_efficiency:discriminative_efficiency","width":"20"},{"column":"qbank_usage\\question_usage_column-question_usage_column","width":"20"},{"column":"qbank_viewcreator\\creator_name_column-creator_name_column","width":"200"},{"column":"qbank_viewcreator\\modifier_name_column-modifier_name_column","width":"200"},{"column":"qbank_viewquestiontype\\question_type_column-question_type_column","width":"20"},{"column":"core_question\\local\\bank\\edit_menu_column-edit_menu_column","width":"50"}] | qbank_columnsortorder |
|
||||
|
||||
Scenario: The teacher sees the question bank with global settings initially
|
||||
Given I am on the "Test quiz Q001" "mod_quiz > question bank" page logged in as "teacher1"
|
||||
When I apply question bank filter "Category" with value "Question category 1"
|
||||
Then I should see "Test question to be seen"
|
||||
And "Last used" "qbank_columnsortorder > column header" should not exist
|
||||
And "Comments" "qbank_columnsortorder > column header" should appear before "Question" "qbank_columnsortorder > column header"
|
||||
And the "style" attribute of "Question" "qbank_columnsortorder > column header" should contain "width: 300px;"
|
||||
|
||||
Scenario: User preference takes precedence over global defaults
|
||||
Given the following "user preferences" exist:
|
||||
| user | preference | value |
|
||||
| teacher1 | qbank_columnsortorder_hiddencols | qbank_comment\comment_count_column-comment_count_column |
|
||||
| teacher1 | qbank_columnsortorder_enabledcol | qbank_viewquestionname\question_name_idnumber_tags_column-question_name_idnumber_tags_column,qbank_usage\question_last_used_column-question_last_used_column,core_question\local\bank\edit_menu_column-edit_menu_column,qbank_editquestion\question_status_column-question_status_column,qbank_history\version_number_column-version_number_column,qbank_statistics\columns\discrimination_index:discrimination_index,qbank_statistics\columns\facility_index:facility_index,qbank_statistics\columns\discriminative_efficiency:discriminative_efficiency,qbank_usage\question_usage_column-question_usage_column,qbank_usage\question_last_used_column-question_last_used_column,qbank_viewcreator\creator_name_column-creator_name_column,qbank_viewcreator\modifier_name_column-modifier_name_column,qbank_viewquestiontype\question_type_column-question_type_column |
|
||||
| teacher1 | qbank_columnsortorder_colsize | [{"column":"qbank_comment\\comment_count_column-comment_count_column","width":"20"},{"column":"qbank_viewquestionname\\question_name_idnumber_tags_column-question_name_idnumber_tags_column","width":"400"},{"column":"qbank_editquestion\\question_status_column-question_status_column","width":"20"},{"column":"qbank_history\\version_number_column-version_number_column","width":"20"},{"column":"qbank_statistics\\columns\\discrimination_index:discrimination_index","width":"20"},{"column":"qbank_statistics\\columns\\facility_index:facility_index","width":"20"},{"column":"qbank_statistics\\columns\\discriminative_efficiency:discriminative_efficiency","width":"20"},{"column":"qbank_usage\\question_usage_column-question_usage_column","width":"20"},{"column":"qbank_viewcreator\\creator_name_column-creator_name_column","width":"200"},{"column":"qbank_viewcreator\\modifier_name_column-modifier_name_column","width":"200"},{"column":"qbank_viewquestiontype\\question_type_column-question_type_column","width":"20"},{"column":"core_question\\local\\bank\\edit_menu_column-edit_menu_column","width":"50"}] |
|
||||
And I am on the "Test quiz Q001" "mod_quiz > question bank" page logged in as "teacher1"
|
||||
When I apply question bank filter "Category" with value "Question category 1"
|
||||
Then "Comments" "qbank_columnsortorder > column header" should not exist
|
||||
And "Question" "qbank_columnsortorder > column header" should appear before "Last used" "qbank_columnsortorder > column header"
|
||||
And the "style" attribute of "Question" "qbank_columnsortorder > column header" should contain "width: 400px;"
|
||||
|
||||
Scenario: User can remove a column in the question bank
|
||||
Given I am on the "Test quiz Q001" "mod_quiz > question bank" page logged in as "teacher1"
|
||||
And I apply question bank filter "Category" with value "Question category 1"
|
||||
And "Comments" "qbank_columnsortorder > column header" should exist
|
||||
And I click on "Actions menu" "link" in the "Comments" "qbank_columnsortorder > column header"
|
||||
And I choose "Remove" in the open action menu
|
||||
Then "Comments" "qbank_columnsortorder > column header" should not exist
|
||||
And I reload the page
|
||||
And "Comments" "qbank_columnsortorder > column header" should not exist
|
||||
|
||||
Scenario: User can add a column in the question bank
|
||||
Given I am on the "Test quiz Q001" "mod_quiz > question bank" page logged in as "teacher1"
|
||||
And I apply question bank filter "Category" with value "Question category 1"
|
||||
And "Last used" "qbank_columnsortorder > column header" should not exist
|
||||
When I press "Add columns"
|
||||
And I follow "Last used"
|
||||
Then "Last used" "qbank_columnsortorder > column header" should exist
|
||||
And I reload the page
|
||||
And "Last used" "qbank_columnsortorder > column header" should exist
|
||||
|
||||
Scenario: User can resize a column in the question bank using modal dialog
|
||||
Given I am on the "Test quiz Q001" "mod_quiz > question bank" page logged in as "teacher1"
|
||||
And I apply question bank filter "Category" with value "Question category 1"
|
||||
And the "style" attribute of "Question" "qbank_columnsortorder > column header" should contain "width: 300px"
|
||||
When I click on "Actions menu" "link" in the "Question" "qbank_columnsortorder > column header"
|
||||
And I choose "Resize" in the open action menu
|
||||
And I set the field "Column width (pixels)" to "400"
|
||||
And I press "Save changes"
|
||||
Then the "style" attribute of "Question" "qbank_columnsortorder > column header" should contain "width: 400px"
|
||||
And I reload the page
|
||||
And the "style" attribute of "Question" "qbank_columnsortorder > column header" should contain "width: 400px"
|
||||
|
||||
Scenario: User can resize a column in the question bank by dragging
|
||||
Given I change the window size to "large"
|
||||
And I am on the "Test quiz Q001" "mod_quiz > question bank" page logged in as "teacher1"
|
||||
And I apply question bank filter "Category" with value "Question category 1"
|
||||
And the "style" attribute of "Question" "qbank_columnsortorder > column header" should contain "width: 300px"
|
||||
When I hover "Question" "qbank_columnsortorder > column header"
|
||||
And I drag "Question" "qbank_columnsortorder > column resize handle" and I drop it in "Status" "qbank_columnsortorder > column header"
|
||||
And the "style" attribute of "Question" "qbank_columnsortorder > column header" should not contain "width: 300px"
|
||||
And I reload the page
|
||||
And the "style" attribute of "Question" "qbank_columnsortorder > column header" should not contain "width: 300px"
|
||||
|
||||
Scenario: User can move a column in the question bank using modal dialog
|
||||
Given I am on the "Test quiz Q001" "mod_quiz > question bank" page logged in as "teacher1"
|
||||
And I apply question bank filter "Category" with value "Question category 1"
|
||||
And "Comments" "qbank_columnsortorder > column header" should appear before "Question" "qbank_columnsortorder > column header"
|
||||
When I click on "Actions menu" "link" in the "Comments" "qbank_columnsortorder > column header"
|
||||
And I choose "Move" in the open action menu
|
||||
And I follow "After \"Question\""
|
||||
Then "Comments" "qbank_columnsortorder > column header" should appear after "Question" "qbank_columnsortorder > column header"
|
||||
And I reload the page
|
||||
And "Comments" "qbank_columnsortorder > column header" should appear after "Question" "qbank_columnsortorder > column header"
|
||||
|
||||
Scenario: User can move a column in the question bank by dragging
|
||||
Given I change the window size to "large"
|
||||
And I am on the "Test quiz Q001" "mod_quiz > question bank" page logged in as "teacher1"
|
||||
And I apply question bank filter "Category" with value "Question category 1"
|
||||
And "Comments" "qbank_columnsortorder > column header" should appear before "Question" "qbank_columnsortorder > column header"
|
||||
When I hover "Comments" "qbank_columnsortorder > column header"
|
||||
And I drag "Comments" "qbank_columnsortorder > column move handle" and I drop it in "Status" "qbank_columnsortorder > column header"
|
||||
Then "Comments" "qbank_columnsortorder > column header" should appear after "Question" "qbank_columnsortorder > column header"
|
||||
And I reload the page
|
||||
And "Comments" "qbank_columnsortorder > column header" should appear after "Question" "qbank_columnsortorder > column header"
|
||||
|
||||
Scenario: Reordering with disabled columns
|
||||
When I log in as "admin"
|
||||
And I navigate to "Plugins > Question bank plugins > Manage question bank plugins" in site administration
|
||||
And I click on "Disable" "link" in the "Question statistics" "table_row"
|
||||
And I click on "Enable" "link" in the "Question statistics" "table_row"
|
||||
And I click on "Disable" "link" in the "Question statistics" "table_row"
|
||||
And I am on the "Course 1" "core_question > course question bank" page
|
||||
Then I should see "Question bank"
|
||||
And "Create a new question" "button" should exist
|
||||
# Really, we are just checking the question bank displayed without errors.
|
@ -20,6 +20,7 @@ defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
use advanced_testcase;
|
||||
use context_course;
|
||||
use core_question\local\bank\column_base;
|
||||
use core_question\local\bank\question_edit_contexts;
|
||||
use core_question\local\bank\view;
|
||||
use moodle_url;
|
||||
@ -71,9 +72,9 @@ class column_manager_test extends advanced_testcase {
|
||||
// Get current view columns.
|
||||
$this->columns = [];
|
||||
foreach ($this->questionbank->get_visiblecolumns() as $column) {
|
||||
$this->columns[] = get_class($column);
|
||||
$this->columns[] = $column->get_column_id();
|
||||
}
|
||||
$this->columnmanager = new column_manager();
|
||||
$this->columnmanager = new column_manager(true);
|
||||
$this->randomstring = random_string();
|
||||
}
|
||||
|
||||
@ -114,7 +115,7 @@ class column_manager_test extends advanced_testcase {
|
||||
$data = $this->{$dataproperty};
|
||||
$this->assertFalse(get_config('qbank_columnsortorder', $setting));
|
||||
$this->assertEmpty(get_user_preferences('qbank_columnsortorder_' . $setting));
|
||||
column_manager::{$function}($data);
|
||||
column_manager::{$function}($data, true);
|
||||
$expected = $csv ? implode(',', $data) : $data;
|
||||
$this->assertEquals($expected, get_config('qbank_columnsortorder', $setting));
|
||||
$this->assertEmpty(get_user_preferences('qbank_columnsortorder_' . $setting));
|
||||
@ -134,7 +135,7 @@ class column_manager_test extends advanced_testcase {
|
||||
$data = $this->{$dataproperty};
|
||||
$this->assertFalse(get_config('qbank_columnsortorder', $setting));
|
||||
$this->assertEmpty(get_user_preferences('qbank_columnsortorder_' . $setting));
|
||||
column_manager::{$function}($data, 'qbank_columnsortorder');
|
||||
column_manager::{$function}($data);
|
||||
$expected = $csv ? implode(',', $data) : $data;
|
||||
$this->assertFalse(get_config('qbank_columnsortorder', $setting));
|
||||
$this->assertEquals($expected, get_user_preferences('qbank_columnsortorder_' . $setting));
|
||||
@ -165,19 +166,17 @@ class column_manager_test extends advanced_testcase {
|
||||
shuffle($neworder);
|
||||
set_config('enabledcol', implode(',', $neworder), 'qbank_columnsortorder');
|
||||
|
||||
$this->columnmanager = new column_manager();
|
||||
$this->columnmanager = new column_manager(true);
|
||||
$columnstosort = [];
|
||||
foreach ($this->columns as $key => $column) {
|
||||
$colname = explode('\\', $column);
|
||||
$columnstosort[end($colname)] = $column;
|
||||
foreach ($this->columns as $column) {
|
||||
$columnstosort[$column] = $column;
|
||||
}
|
||||
|
||||
$sortedcolumns = $this->columnmanager->get_sorted_columns($columnstosort);
|
||||
|
||||
$expectedorder = ['checkbox_column' => 0];
|
||||
foreach ($neworder as $key => $column) {
|
||||
$colname = explode('\\', $column);
|
||||
$expectedorder[end($colname)] = $column;
|
||||
$expectedorder = ['core_question\local\bank\checkbox_column' . column_base::ID_SEPARATOR . 'checkbox_column' => 0];
|
||||
foreach ($neworder as $columnid) {
|
||||
$expectedorder[$columnid] = $columnid;
|
||||
}
|
||||
$this->assertSame($expectedorder, $sortedcolumns);
|
||||
}
|
||||
@ -219,13 +218,14 @@ class column_manager_test extends advanced_testcase {
|
||||
public function test_plugin_enabled_disabled_observers(): void {
|
||||
$neworder = $this->columnmanager->get_sorted_columns($this->columns);
|
||||
shuffle($neworder);
|
||||
set_columnbank_order::execute($neworder);
|
||||
$this->columnmanager::set_column_order($neworder, true);
|
||||
// Get the list of enabled columns, excluding core columns (we can't disable those).
|
||||
$currentconfig = get_config('qbank_columnsortorder', 'enabledcol');
|
||||
$currentconfig = array_filter(explode(',', $currentconfig), fn($class) => !str_starts_with($class, 'core'));
|
||||
// Pick a column at random and get its plugin name.
|
||||
$class = $currentconfig[array_rand($currentconfig, 1)];
|
||||
$randomplugintodisable = explode('\\', $class)[0];
|
||||
$randomcolumnid = $currentconfig[array_rand($currentconfig, 1)];
|
||||
[$randomcolumnclass] = explode(column_base::ID_SEPARATOR, $randomcolumnid, 2);
|
||||
[$randomplugintodisable] = explode('\\', $randomcolumnclass);
|
||||
$olddisabledconfig = get_config('qbank_columnsortorder', 'disabledcol');
|
||||
\core\event\qbank_plugin_disabled::create_for_plugin($randomplugintodisable)->trigger();
|
||||
$newdisabledconfig = get_config('qbank_columnsortorder', 'disabledcol');
|
||||
@ -260,7 +260,7 @@ class column_manager_test extends advanced_testcase {
|
||||
set_config('disabledcol', implode(',', $disabledcols), 'qbank_columnsortorder');
|
||||
|
||||
// Enable one of the disabled plugins.
|
||||
$this->columnmanager = new column_manager();
|
||||
$this->columnmanager = new column_manager(true);
|
||||
$this->columnmanager->enable_columns($randomplugin1);
|
||||
// The enabledcol setting should now contain all columns except the remaining disabled plugin.
|
||||
$expectedenabled = array_filter($this->columns, fn($column) => !str_starts_with($column, $randomplugin2));
|
||||
@ -291,11 +291,12 @@ class column_manager_test extends advanced_testcase {
|
||||
|
||||
set_config('disabledcol', implode(',', $disabledcols), 'qbank_columnsortorder');
|
||||
|
||||
$this->columnmanager = new column_manager();
|
||||
$this->columnmanager = new column_manager(true);
|
||||
$expecteddisablednames = [];
|
||||
foreach ($disabledcols as $disabledcol) {
|
||||
$columnobject = new $disabledcol($this->questionbank);
|
||||
$expecteddisablednames[] = (object) [
|
||||
foreach ($disabledcols as $disabledcolid) {
|
||||
[$columnclass, $columnname] = explode(column_base::ID_SEPARATOR, $disabledcolid, 2);
|
||||
$columnobject = $columnclass::from_column_name($this->questionbank, $columnname);
|
||||
$expecteddisablednames[$disabledcolid] = (object) [
|
||||
'disabledname' => $columnobject->get_title(),
|
||||
];
|
||||
}
|
||||
|
68
question/bank/columnsortorder/tests/external/set_column_size_test.php
vendored
Normal file
68
question/bank/columnsortorder/tests/external/set_column_size_test.php
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
<?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 qbank_columnsortorder\external;
|
||||
|
||||
use qbank_columnsortorder\column_manager;
|
||||
use qbank_columnsortorder\tests\external_function_testcase;
|
||||
|
||||
// phpcs:disable moodle.PHPUnit.TestCaseNames.Missing
|
||||
// This class inherits its test methods from the parent class.
|
||||
|
||||
/**
|
||||
* Unit tests for qbank_columnsortorder external API.
|
||||
*
|
||||
* @package qbank_columnsortorder
|
||||
* @copyright 2023 Catalyst IT Europe Ltd.
|
||||
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @covers \qbank_columnsortorder\external\set_column_size
|
||||
*/
|
||||
class set_column_size_test extends external_function_testcase {
|
||||
|
||||
/**
|
||||
* @var string Fully-qualified external function class to test.
|
||||
*/
|
||||
protected $testclass = '\qbank_columnsortorder\external\set_column_size';
|
||||
|
||||
/**
|
||||
* @var string The name of the setting used to store the data.
|
||||
*/
|
||||
protected $setting = 'colsize';
|
||||
|
||||
/**
|
||||
* @var bool Whether the data is stored as a comma-separated list.
|
||||
*/
|
||||
protected $csv = false;
|
||||
|
||||
/**
|
||||
* Generate a list of random column sizes.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function generate_test_data(): string {
|
||||
$columnsortorder = new column_manager();
|
||||
$questionlistcolumns = $columnsortorder->get_columns();
|
||||
$columnsizes = [];
|
||||
foreach ($questionlistcolumns as $columnnobject) {
|
||||
$columnsizes[] = (object)[
|
||||
'column' => $columnnobject->name,
|
||||
'width' => rand(1, 100) . 'px'
|
||||
];
|
||||
}
|
||||
return json_encode($columnsizes);
|
||||
}
|
||||
}
|
61
question/bank/columnsortorder/tests/external/set_columnbank_order_test.php
vendored
Normal file
61
question/bank/columnsortorder/tests/external/set_columnbank_order_test.php
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
<?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 qbank_columnsortorder\external;
|
||||
|
||||
use qbank_columnsortorder\column_manager;
|
||||
use qbank_columnsortorder\tests\external_function_testcase;
|
||||
|
||||
// phpcs:disable moodle.PHPUnit.TestCaseNames.Missing
|
||||
// This class inherits its test methods from the parent class.
|
||||
|
||||
/**
|
||||
* Unit tests for qbank_columnsortorder external API.
|
||||
*
|
||||
* @package qbank_columnsortorder
|
||||
* @copyright 2023 Catalyst IT Europe Ltd.
|
||||
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @covers \qbank_columnsortorder\external\set_columnbank_order
|
||||
*/
|
||||
class set_columnbank_order_test extends external_function_testcase {
|
||||
|
||||
/**
|
||||
* @var string Fully-qualified external function class to test.
|
||||
*/
|
||||
protected $testclass = '\qbank_columnsortorder\external\set_columnbank_order';
|
||||
|
||||
/**
|
||||
* @var string The name of the setting used to store the data.
|
||||
*/
|
||||
protected $setting = 'enabledcol';
|
||||
|
||||
/**
|
||||
* Return a randomly-ordered list of columns.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function generate_test_data(): array {
|
||||
$columnsortorder = new column_manager();
|
||||
$questionlistcolumns = $columnsortorder->get_columns();
|
||||
$columnclasses = [];
|
||||
foreach ($questionlistcolumns as $columnnobject) {
|
||||
$columnclasses[] = $columnnobject->class;
|
||||
}
|
||||
shuffle($columnclasses);
|
||||
return $columnclasses;
|
||||
}
|
||||
}
|
57
question/bank/columnsortorder/tests/external/set_hidden_columns_test.php
vendored
Normal file
57
question/bank/columnsortorder/tests/external/set_hidden_columns_test.php
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
<?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 qbank_columnsortorder\external;
|
||||
|
||||
use qbank_columnsortorder\column_manager;
|
||||
use qbank_columnsortorder\tests\external_function_testcase;
|
||||
|
||||
// phpcs:disable moodle.PHPUnit.TestCaseNames.Missing
|
||||
// This class inherits its test methods from the parent class.
|
||||
|
||||
/**
|
||||
* Unit tests for qbank_columnsortorder external API.
|
||||
*
|
||||
* @package qbank_columnsortorder
|
||||
* @copyright 2023 Catalyst IT Europe Ltd.
|
||||
* @author Mark Johnson <mark.johnson@catalyst-eu.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @covers \qbank_columnsortorder\external\set_hidden_columns
|
||||
*/
|
||||
class set_hidden_columns_test extends external_function_testcase {
|
||||
|
||||
/**
|
||||
* @var string Fully-qualified external function class to test.
|
||||
*/
|
||||
protected $testclass = '\qbank_columnsortorder\external\set_hidden_columns';
|
||||
|
||||
/**
|
||||
* @var string The name of the setting used to store the data.
|
||||
*/
|
||||
protected $setting = 'hiddencols';
|
||||
|
||||
/**
|
||||
* Return a random list of hidden column names.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function generate_test_data(): array {
|
||||
$columnsortorder = new column_manager();
|
||||
$questionlistcolumns = $columnsortorder->get_columns();
|
||||
$hiddencolumns = array_slice($questionlistcolumns, rand(0, count($questionlistcolumns) - 1));
|
||||
return array_map(fn($column) => $column->name, $hiddencolumns);
|
||||
}
|
||||
}
|
@ -26,6 +26,6 @@
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->component = 'qbank_columnsortorder';
|
||||
$plugin->version = 2023052200;
|
||||
$plugin->version = 2023052201;
|
||||
$plugin->requires = 2023041800;
|
||||
$plugin->maturity = MATURITY_STABLE;
|
||||
|
@ -110,4 +110,7 @@ class comment_count_column extends column_base {
|
||||
return ['pr-3'];
|
||||
}
|
||||
|
||||
public function get_default_width(): int {
|
||||
return 150;
|
||||
}
|
||||
}
|
||||
|
@ -210,10 +210,8 @@ Feature: Show statistics in question bank
|
||||
And I run the scheduled task "\quiz_statistics\task\recalculate"
|
||||
# Confirm the "Needs checking?" column matches the expected values based on students' answers
|
||||
When I am on the "Quiz 3" "mod_quiz > question bank" page logged in as "admin"
|
||||
Then the following should exist in the "categoryquestions" table:
|
||||
| Question | Needs checking? |
|
||||
| MCA | Likely |
|
||||
| MCB | Very likely |
|
||||
| MCC | Unlikely |
|
||||
| MCD | Likely |
|
||||
| MCE | Very likely |
|
||||
Then "Likely" "text" should exist in the "MCA" "table_row"
|
||||
And "Very likely" "text" should exist in the "MCB" "table_row"
|
||||
And "Unlikely" "text" should exist in the "MCC" "table_row"
|
||||
And "Likely" "text" should exist in the "MCD" "table_row"
|
||||
And "Very likely" "text" should exist in the "MCE" "table_row"
|
||||
|
@ -72,4 +72,7 @@ class viewquestionname_column_helper extends column_base {
|
||||
return 'q.name';
|
||||
}
|
||||
|
||||
public function get_default_width(): int {
|
||||
return 250;
|
||||
}
|
||||
}
|
||||
|
@ -52,4 +52,7 @@ class question_type_column extends column_base {
|
||||
return 'q.qtype';
|
||||
}
|
||||
|
||||
public function get_default_width(): int {
|
||||
return 45;
|
||||
}
|
||||
}
|
||||
|
@ -96,4 +96,7 @@ class checkbox_column extends column_base {
|
||||
return ['q.id'];
|
||||
}
|
||||
|
||||
public function get_default_width(): int {
|
||||
return 25;
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ namespace core_question\local\bank;
|
||||
abstract class column_base extends view_component {
|
||||
|
||||
/**
|
||||
* @const string A separator for joining column attributes together into a unique ID string.
|
||||
* @var string A separator for joining column attributes together into a unique ID string.
|
||||
*/
|
||||
const ID_SEPARATOR = '-';
|
||||
|
||||
@ -101,7 +101,8 @@ abstract class column_base extends view_component {
|
||||
/**
|
||||
* Output the column header cell.
|
||||
*
|
||||
* @params column_action_base[] A list of column actions to include in the header.
|
||||
* @param column_action_base[] $columnactions A list of column actions to include in the header.
|
||||
* @param string $width A CSS width property value.
|
||||
*/
|
||||
public function display_header(array $columnactions = [], string $width = ''): void {
|
||||
global $PAGE;
|
||||
@ -253,7 +254,7 @@ abstract class column_base extends view_component {
|
||||
$tag = 'td';
|
||||
$attr = [
|
||||
'class' => $this->get_classes(),
|
||||
'data-pluginname' => get_class($this),
|
||||
'data-columnid' => $this->get_column_id(),
|
||||
];
|
||||
if ($this->isheading) {
|
||||
$tag = 'th';
|
||||
@ -319,6 +320,15 @@ abstract class column_base extends view_component {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the default column width in pixels.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function get_default_width(): int {
|
||||
return 120;
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the contents of this column.
|
||||
* @param object $question the row from the $question table, augmented with extra information.
|
||||
|
@ -69,6 +69,6 @@ class column_manager_base {
|
||||
* @return string CSS width property value.
|
||||
*/
|
||||
public function get_column_width(column_base $column): string {
|
||||
return '';
|
||||
return $column->get_default_width() . 'px';
|
||||
}
|
||||
}
|
||||
|
@ -388,14 +388,7 @@ class view {
|
||||
$newpluginclasscolumns = [];
|
||||
$corequestionbankcolumns = [
|
||||
'core_question\local\bank\checkbox_column' . column_base::ID_SEPARATOR . 'checkbox_column',
|
||||
'qbank_viewquestiontype\question_type_column' . column_base::ID_SEPARATOR . 'question_type_column',
|
||||
'qbank_viewquestionname\question_name_idnumber_tags_column' . column_base::ID_SEPARATOR .
|
||||
'question_name_idnumber_tags_column',
|
||||
'core_question\local\bank\edit_menu_column' . column_base::ID_SEPARATOR . 'edit_menu_column',
|
||||
'qbank_editquestion\question_status_column' . column_base::ID_SEPARATOR . 'question_status_column',
|
||||
'qbank_history\version_number_column' . column_base::ID_SEPARATOR . 'version_number_column',
|
||||
'qbank_viewcreator\creator_name_column' . column_base::ID_SEPARATOR . 'creator_name_column',
|
||||
'qbank_comment\comment_count_column' . column_base::ID_SEPARATOR . 'comment_count_column',
|
||||
];
|
||||
|
||||
if (question_get_display_preference('qbshowtext', 0, PARAM_INT, new \moodle_url(''))) {
|
||||
@ -1417,7 +1410,7 @@ class view {
|
||||
// Start of the table.
|
||||
echo \html_writer::start_tag('table', [
|
||||
'id' => 'categoryquestions',
|
||||
'class' => 'question-bank-table generaltable table-responsive',
|
||||
'class' => 'question-bank-table generaltable',
|
||||
'data-defaultsort' => json_encode($this->sort),
|
||||
]);
|
||||
|
||||
|
@ -174,12 +174,24 @@ class behat_core_question extends behat_question_base {
|
||||
* @param string $questionname the question name.
|
||||
*/
|
||||
public function i_action_the_question($action, $questionname) {
|
||||
$this->execute('behat_action_menu::i_choose_in_the_named_menu_in_container', [
|
||||
$action,
|
||||
get_string('edit', 'core'),
|
||||
$questionname,
|
||||
'table_row',
|
||||
]);
|
||||
if ($this->running_javascript()) {
|
||||
// This method isn't allowed unless Javascript is running.
|
||||
$this->execute('behat_action_menu::i_open_the_action_menu_in', [
|
||||
$questionname,
|
||||
'table_row',
|
||||
]);
|
||||
$this->execute('behat_action_menu::i_choose_in_the_open_action_menu', [
|
||||
$action
|
||||
]);
|
||||
} else {
|
||||
// This method doesn't open the menu correctly when Javascript is running.
|
||||
$this->execute('behat_action_menu::i_choose_in_the_named_menu_in_container', [
|
||||
$action,
|
||||
get_string('edit', 'core'),
|
||||
$questionname,
|
||||
'table_row',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user