MDL-76418 course: section action menu item to show permlink to section

This commit is contained in:
Stephan Robotta 2022-11-18 13:23:24 +01:00
parent 0780e87f06
commit a8de5c5002
11 changed files with 200 additions and 2 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -30,6 +30,7 @@ define(
'core/str',
'core/url',
'core/yui',
'core/modal_copy_to_clipboard',
'core/modal_factory',
'core/modal_events',
'core/key_codes',
@ -46,6 +47,7 @@ define(
str,
url,
Y,
ModalCopyToClipboard,
ModalFactory,
ModalEvents,
KeyCodes,
@ -964,6 +966,15 @@ define(
sectionElement = actionItem.closest(SELECTOR.SECTIONLI),
sectionId = actionItem.closest(SELECTOR.SECTIONACTIONMENU).attr('data-sectionid');
if (actionItem.attr('data-action') === 'permalink') {
e.preventDefault();
ModalCopyToClipboard.create({
text: actionItem.attr('href'),
}, str.get_string('sectionlink', 'course')
);
return;
}
let isExecuted = true;
if (actionItem.attr('data-confirm')) {
// Action requires confirmation.

View File

@ -272,6 +272,25 @@ class controlmenu implements named_templatable, renderable {
];
}
}
if (has_any_capability(['moodle/course:movesections', 'moodle/course:update', 'moodle/course:sectionvisibility'],
$coursecontext)
) {
$sectionlink = new moodle_url(
'/course/view.php',
['id' => $course->id],
'sectionid-' . $section->id . '-title'
);
$controls['permalink'] = [
'url' => $sectionlink,
'icon' => 'i/link',
'name' => get_string('sectionlink', 'course'),
'pixattr' => ['class' => ''],
'attr' => [
'class' => 'icon',
'data-action' => 'permalink',
],
];
}
return $controls;
}

View File

@ -120,6 +120,7 @@ $string['relativedatessubmissionduedateafter'] = '{$a->datediffstr} after course
$string['relativedatessubmissionduedatebefore'] = '{$a->datediffstr} before course start';
$string['searchactivitiesbyname'] = 'Search for activities by name';
$string['searchresults'] = 'Search results: {$a}';
$string['sectionlink'] = 'Permalink';
$string['submitsearch'] = 'Submit search';
$string['studentsatriskincourse'] = 'Students at risk in {$a} course';
$string['studentsatriskinfomessage'] = 'Hi {$a->userfirstname},

View File

@ -319,6 +319,7 @@ $string['cookiesenabledonlysession_help'] = 'This site uses one session cookie,
$string['cookiesnotenabled'] = 'Unfortunately, cookies are currently not enabled in your browser';
$string['cookiesnotice'] = 'Cookies notice';
$string['copy'] = 'copy';
$string['copytoclipboard'] = 'Copy to clipboard';
$string['copyasnoun'] = 'copy';
$string['copycourse'] = 'Copy course';
$string['copyingcoursefiles'] = 'Copying course files';

View File

@ -0,0 +1,3 @@
define("core/modal_copy_to_clipboard",["exports","core/modal","core/modal_registry","core/modal_factory","core/copy_to_clipboard"],(function(_exports,_modal,_modal_registry,_modal_factory,_copy_to_clipboard){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}}function _defineProperty(obj,key,value){return key in obj?Object.defineProperty(obj,key,{value:value,enumerable:!0,configurable:!0,writable:!0}):obj[key]=value,obj}Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_modal=_interopRequireDefault(_modal),_modal_registry=_interopRequireDefault(_modal_registry),_modal_factory=_interopRequireDefault(_modal_factory);class CopyToClipboardModal extends _modal.default{constructor(){super(...arguments),this.setRemoveOnClose(!0)}registerEventListeners(){super.registerEventListeners(...arguments),this.getRoot().get(0).addEventListener("click",(e=>{e.target.closest('[data-action="copytoclipboard"]')&&this.getRoot().get(0).contains(e.target)&&setTimeout(this.destroy.bind(this))}))}static async create(){let{text:text,useTextArea:useTextArea=!1}=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},title=arguments.length>1?arguments[1]:void 0;_modal_registry.default.get(this.TYPE)||_modal_registry.default.register(this.TYPE,this,this.TEMPLATE);const modal=await _modal_factory.default.create({type:this.TYPE,templateContext:{text:text,useTextArea:useTextArea}});title&&modal.setTitle(title),modal.show()}}return _exports.default=CopyToClipboardModal,_defineProperty(CopyToClipboardModal,"TYPE","core/copytoclipboard"),_defineProperty(CopyToClipboardModal,"TEMPLATE","core/modal_copytoclipboard"),_exports.default}));
//# sourceMappingURL=modal_copy_to_clipboard.min.js.map

View File

@ -0,0 +1 @@
{"version":3,"file":"modal_copy_to_clipboard.min.js","sources":["../src/modal_copy_to_clipboard.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 * Contain the logic for the copy to clipboard modal, i.e. the modal contains a\n * readonly input text field, that contains a value. Clicking on the single\n * button \"Copy to clipboard\" in the footer, puts the content of the input\n * text field into the clipboard and closes the modal.\n *\n * Usage:\n * ModalCopyToClipboard.create(string:<stringToCopy>, string:<modalTitle>|null);\n *\n * @module core/modal_copy_to_clipboard\n * @copyright 2023 Stephan Robotta <stephan.robotta@bfh.ch>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Modal from 'core/modal';\nimport ModalRegistry from 'core/modal_registry';\nimport ModalFactory from 'core/modal_factory';\nimport 'core/copy_to_clipboard';\n\nexport default class CopyToClipboardModal extends Modal {\n static TYPE = 'core/copytoclipboard';\n static TEMPLATE = 'core/modal_copytoclipboard';\n\n constructor(...config) {\n // Override the constructor to set the removeOnClose property, and show the modal.\n super(...config);\n this.setRemoveOnClose(true);\n }\n\n /**\n * Set up all the event handling for the modal.\n * This is an override of the parent method, adding an event listener to close upon the action.\n *\n * @param {array} args\n */\n registerEventListeners(...args) {\n super.registerEventListeners(...args);\n\n this.getRoot().get(0).addEventListener('click', (e) => {\n if (!e.target.closest('[data-action=\"copytoclipboard\"]')) {\n return;\n }\n\n if (!this.getRoot().get(0).contains(e.target)) {\n return;\n }\n\n // Note: We must call destroy() here, because the copy-to-clipboard action listens on the document,\n // which will be processed after this event listener has been processed.\n // By placing this in a setTimeout we move its processing to after the event loop has finished.\n setTimeout(this.destroy.bind(this));\n });\n }\n\n /**\n * Create a new instance of the Modal. Set the text for the input readonly field that is copied.\n * and set the modal title.\n *\n * @param {Object} data used in the template\n * @param {string} data.text the text to copy to the clipboard\n * @param {boolean} data.useTextArea when the text to copy is displayed in a textarea, default is input\n * @param {string|null} title\n * @returns {Promise<void>}\n */\n static async create(\n {\n text,\n useTextArea = false,\n } = {},\n title\n ) {\n if (!ModalRegistry.get(this.TYPE)) {\n ModalRegistry.register(this.TYPE, this, this.TEMPLATE);\n }\n\n const modal = await ModalFactory.create({\n type: this.TYPE,\n templateContext: {\n text: text,\n useTextArea: useTextArea,\n },\n });\n if (title) {\n modal.setTitle(title);\n }\n modal.show();\n }\n}"],"names":["CopyToClipboardModal","Modal","constructor","setRemoveOnClose","registerEventListeners","getRoot","get","addEventListener","e","target","closest","this","contains","setTimeout","destroy","bind","text","useTextArea","title","ModalRegistry","TYPE","register","TEMPLATE","modal","ModalFactory","create","type","templateContext","setTitle","show"],"mappings":"grBAkCqBA,6BAA6BC,eAI9CC,uCAGSC,kBAAiB,GAS1BC,+BACUA,0CAEDC,UAAUC,IAAI,GAAGC,iBAAiB,SAAUC,IACxCA,EAAEC,OAAOC,QAAQ,oCAIjBC,KAAKN,UAAUC,IAAI,GAAGM,SAASJ,EAAEC,SAOtCI,WAAWF,KAAKG,QAAQC,KAAKJ,oCAejCK,KACIA,KADJC,YAEIA,aAAc,0DACd,GACJC,6CAEKC,wBAAcb,IAAIK,KAAKS,+BACVC,SAASV,KAAKS,KAAMT,KAAMA,KAAKW,gBAG3CC,YAAcC,uBAAaC,OAAO,CACpCC,KAAMf,KAAKS,KACXO,gBAAiB,CACbX,KAAMA,KACNC,YAAaA,eAGjBC,OACAK,MAAMK,SAASV,OAEnBK,MAAMM,qEAlEO7B,4BACH,wCADGA,gCAEC"}

View File

@ -0,0 +1,104 @@
// 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/>.
/**
* Contain the logic for the copy to clipboard modal, i.e. the modal contains a
* readonly input text field, that contains a value. Clicking on the single
* button "Copy to clipboard" in the footer, puts the content of the input
* text field into the clipboard and closes the modal.
*
* Usage:
* ModalCopyToClipboard.create(string:<stringToCopy>, string:<modalTitle>|null);
*
* @module core/modal_copy_to_clipboard
* @copyright 2023 Stephan Robotta <stephan.robotta@bfh.ch>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import Modal from 'core/modal';
import ModalRegistry from 'core/modal_registry';
import ModalFactory from 'core/modal_factory';
import 'core/copy_to_clipboard';
export default class CopyToClipboardModal extends Modal {
static TYPE = 'core/copytoclipboard';
static TEMPLATE = 'core/modal_copytoclipboard';
constructor(...config) {
// Override the constructor to set the removeOnClose property, and show the modal.
super(...config);
this.setRemoveOnClose(true);
}
/**
* Set up all the event handling for the modal.
* This is an override of the parent method, adding an event listener to close upon the action.
*
* @param {array} args
*/
registerEventListeners(...args) {
super.registerEventListeners(...args);
this.getRoot().get(0).addEventListener('click', (e) => {
if (!e.target.closest('[data-action="copytoclipboard"]')) {
return;
}
if (!this.getRoot().get(0).contains(e.target)) {
return;
}
// Note: We must call destroy() here, because the copy-to-clipboard action listens on the document,
// which will be processed after this event listener has been processed.
// By placing this in a setTimeout we move its processing to after the event loop has finished.
setTimeout(this.destroy.bind(this));
});
}
/**
* Create a new instance of the Modal. Set the text that is being copied. By default, the text is put into the
* value of an input readonly field. If useTextArea is set to true, the text is rendered in a textarea element.
* The optional title argument is for the modal title. If not set, the generic string "copy to clipboard" is used.
*
* @param {Object} data used in the template
* @param {string} data.text the text to copy to the clipboard
* @param {boolean} data.useTextArea when the text to copy is displayed in a textarea, default is input
* @param {string|null} title
* @returns {Promise<void>}
*/
static async create(
{
text,
useTextArea = false,
} = {},
title
) {
if (!ModalRegistry.get(this.TYPE)) {
ModalRegistry.register(this.TYPE, this, this.TEMPLATE);
}
const modal = await ModalFactory.create({
type: this.TYPE,
templateContext: {
text: text,
useTextArea: useTextArea,
},
});
if (title) {
modal.setTitle(title);
}
modal.show();
}
}

View File

@ -238,6 +238,7 @@ class icon_system_fontawesome extends icon_system_font {
'core:i/enrolusers' => 'fa-user-plus',
'core:i/expired' => 'fa-exclamation text-warning',
'core:i/export' => 'fa-download',
'core:i/link' => 'fa-link',
'core:i/externallink' => 'fa-external-link',
'core:i/files' => 'fa-file',
'core:i/filter' => 'fa-filter',

View 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 core/modal_copytoclipboard
This template renders a modal. The body contains a readonly input text field.
The Footer contains a button "Copy to clipboard" that copies the content
of the text field into the clipboard.
The purpose of the dialog element is to copy a permalink of a section into
the clipboard. Thus, the header of the modal dialog contains the label "Permalink".
Example context (json):
{
"text": "content for the input field that is being copied to the clipboard",
}
}}
{{< core/modal }}
{{$title}}{{#str}} copytoclipboard, core {{/str}}{{/title}}
{{$body}}
{{> core/local/toast/wrapper }}
{{^useTextArea}}
<input type="text" id="directionlink-modal-{{uniqid}}" class="form-control bg-white" readonly {{!
}} value="{{{text}}}"{{!
}}/>
{{/useTextArea}}
{{#useTextArea}}
<textarea id="directionlink-modal-{{uniqid}}" class="form-control bg-white" readonly {{!
}}>{{{text}}}</textarea>
{{/useTextArea}}
{{/body}}
{{$footer}}
<a {{!
}} href="#" {{!
}} class="btn btn-primary" {{!
}} data-action="copytoclipboard" {{!
}} data-clipboard-target="#directionlink-modal-{{uniqid}}" {{!
}} data-clipboard-success-message="{{#quote}}{{#str}} textcopiedtoclipboard, core {{/str}}{{/quote}}" {{!
}}>
{{#pix}} t/copy, core, {{#str}} copytoclipboard, core {{/str}} {{/pix}}
{{#str}} copytoclipboard, core {{/str}}
</a>
{{/footer}}
{{/ core/modal }}