From 76c107eac15d7433e0a86fe008977876df2ba3cf Mon Sep 17 00:00:00 2001 From: Issam Taboubi Date: Tue, 15 Sep 2015 14:53:05 -0400 Subject: [PATCH] MDL-50482 tool_lp: Add ability to duplicate a learning plan template --- ...tedelete.min.js => templateactions.min.js} | 2 +- .../{templatedelete.js => templateactions.js} | 39 ++++++++++++-- admin/tool/lp/classes/api.php | 30 +++++++++++ admin/tool/lp/classes/external.php | 51 +++++++++++++++++++ admin/tool/lp/db/services.php | 8 +++ admin/tool/lp/lang/en/tool_lp.php | 1 + .../templates/manage_templates_page.mustache | 14 +++-- admin/tool/lp/tests/externallib_test.php | 44 ++++++++++++++++ 8 files changed, 180 insertions(+), 9 deletions(-) rename admin/tool/lp/amd/build/{templatedelete.min.js => templateactions.min.js} (72%) rename admin/tool/lp/amd/src/{templatedelete.js => templateactions.js} (80%) diff --git a/admin/tool/lp/amd/build/templatedelete.min.js b/admin/tool/lp/amd/build/templateactions.min.js similarity index 72% rename from admin/tool/lp/amd/build/templatedelete.min.js rename to admin/tool/lp/amd/build/templateactions.min.js index 4a46244b6f7..d180b15f3a7 100644 --- a/admin/tool/lp/amd/build/templatedelete.min.js +++ b/admin/tool/lp/amd/build/templateactions.min.js @@ -1 +1 @@ -define(["jquery","core/templates","core/ajax","core/notification","core/str"],function(a,b,c,d,e){var f=0,g=0,h=function(c,d){a('[data-region="managetemplates"]').replaceWith(c),b.runTemplateJS(d)},i=function(a){b.render("tool_lp/manage_templates_page",a).done(h).fail(d.exception)},j=function(){var a=c.call([{methodname:"tool_lp_delete_template",args:{id:g}},{methodname:"tool_lp_data_for_templates_manage_page",args:{pagecontext:{contextid:f}}}]);a[1].done(i).fail(d.exception)},k=function(b){b.preventDefault();var f=a(this).attr("data-templateid");g=f;var h=c.call([{methodname:"tool_lp_read_template",args:{id:g}}]);h[0].done(function(a){e.get_strings([{key:"confirm",component:"moodle"},{key:"deletetemplate",component:"tool_lp",param:a.shortname},{key:"delete",component:"moodle"},{key:"cancel",component:"moodle"}]).done(function(a){d.confirm(a[0],a[1],a[2],a[3],j)}).fail(d.exception)}).fail(d.exception)};return{deleteHandler:k,init:function(a){f=a}}}); \ No newline at end of file +define(["jquery","core/templates","core/ajax","core/notification","core/str"],function(a,b,c,d,e){var f=0,g=0,h=function(c,d){a('[data-region="managetemplates"]').replaceWith(c),b.runTemplateJS(d)},i=function(a){b.render("tool_lp/manage_templates_page",a).done(h).fail(d.exception)},j=function(){var a=c.call([{methodname:"tool_lp_delete_template",args:{id:g}},{methodname:"tool_lp_data_for_templates_manage_page",args:{pagecontext:{contextid:f}}}]);a[1].done(i).fail(d.exception)},k=function(b){b.preventDefault(),g=a(this).attr("data-templateid");var e=c.call([{methodname:"tool_lp_duplicate_template",args:{id:g}},{methodname:"tool_lp_data_for_templates_manage_page",args:{pagecontext:{contextid:f}}}]);e[1].done(i).fail(d.exception)},l=function(b){b.preventDefault();var f=a(this).attr("data-templateid");g=f;var h=c.call([{methodname:"tool_lp_read_template",args:{id:g}}]);h[0].done(function(a){e.get_strings([{key:"confirm",component:"moodle"},{key:"deletetemplate",component:"tool_lp",param:a.shortname},{key:"delete",component:"moodle"},{key:"cancel",component:"moodle"}]).done(function(a){d.confirm(a[0],a[1],a[2],a[3],j)}).fail(d.exception)}).fail(d.exception)};return{deleteHandler:l,duplicateHandler:k,init:function(a){f=a}}}); \ No newline at end of file diff --git a/admin/tool/lp/amd/src/templatedelete.js b/admin/tool/lp/amd/src/templateactions.js similarity index 80% rename from admin/tool/lp/amd/src/templatedelete.js rename to admin/tool/lp/amd/src/templateactions.js index 26694e14b29..2416ed5f5e2 100644 --- a/admin/tool/lp/amd/src/templatedelete.js +++ b/admin/tool/lp/amd/src/templateactions.js @@ -14,9 +14,9 @@ // along with Moodle. If not, see . /** - * Delete learning plan templates via ajax. + * Handle actions on learning plan templates via ajax. * - * @module tool_lp/templatedelete + * @module tool_lp/templateactions * @package tool_lp * @copyright 2015 Damyon Wiese * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later @@ -75,6 +75,31 @@ define(['jquery', 'core/templates', 'core/ajax', 'core/notification', 'core/str' requests[1].done(reloadList).fail(notification.exception); }; + /** + * Duplicate a template and reload the page. + * @method doDuplicate + * @param {Event} e + */ + var doDuplicate = function(e) { + e.preventDefault(); + + templateid = $(this).attr('data-templateid'); + + // We are chaining ajax requests here. + var requests = ajax.call([{ + methodname: 'tool_lp_duplicate_template', + args: { id: templateid } + }, { + methodname: 'tool_lp_data_for_templates_manage_page', + args: { + pagecontext: { + contextid: pagecontextid + } + } + }]); + requests[1].done(reloadList).fail(notification.exception); + }; + /** * Handler for "Delete learning plan template" actions. * @method confirmDelete @@ -110,8 +135,7 @@ define(['jquery', 'core/templates', 'core/ajax', 'core/notification', 'core/str' }; - - return /** @alias module:tool_lp/templatedelete */ { + return /** @alias module:tool_lp/templateactions */ { // Public variables and functions. /** * Expose the event handler for the delete. @@ -120,6 +144,13 @@ define(['jquery', 'core/templates', 'core/ajax', 'core/notification', 'core/str' */ deleteHandler: confirmDelete, + /** + * Expose the event handler for the duplicate. + * @method duplicateHandler + * @param {Event} e + */ + duplicateHandler: doDuplicate, + /** * Initialise the module. * @method init diff --git a/admin/tool/lp/classes/api.php b/admin/tool/lp/classes/api.php index 3b0df189f24..c96729de8ca 100644 --- a/admin/tool/lp/classes/api.php +++ b/admin/tool/lp/classes/api.php @@ -756,6 +756,36 @@ class api { return $template; } + /** + * Duplicate a learning plan template. + * + * Requires tool/lp:templatemanage capability at the template context. + * + * @param int $id the template id. + * @return template + */ + public static function duplicate_template($id) { + $template = new template($id); + + // First we do a permissions check. + require_capability('tool/lp:templatemanage', $template->get_context()); + + // OK - all set. + $templatecompetency = new template_competency(); + $competencies = $templatecompetency->list_competencies($id, false); + + // Adding the suffix copy. + $template->set_shortname(get_string('duplicateditemname', 'tool_lp', $template->get_shortname())); + + $duplicatedtemplate = $template->create(); + + // Associate each competency for the duplicated template. + foreach ($competencies as $competency) { + self::add_competency_to_template($duplicatedtemplate->get_id(), $competency->get_id()); + } + return $duplicatedtemplate; + } + /** * Delete a learning plan template by id. * diff --git a/admin/tool/lp/classes/external.php b/admin/tool/lp/classes/external.php index bcc3ee6b19b..0ae0e215bf8 100644 --- a/admin/tool/lp/classes/external.php +++ b/admin/tool/lp/classes/external.php @@ -2578,6 +2578,57 @@ class external extends external_api { return new external_value(PARAM_BOOL, 'True if the update was successful'); } + /** + * Returns description of duplicate_template() parameters. + * + * @return \external_function_parameters + */ + public static function duplicate_template_parameters() { + $templateid = new external_value( + PARAM_INT, + 'The template id', + VALUE_REQUIRED + ); + + $params = array( + 'id' => $templateid + ); + return new external_function_parameters($params); + } + + /** + * Expose to AJAX. + * @return boolean + */ + public static function duplicate_template_is_allowed_from_ajax() { + return true; + } + + /** + * Duplicate a learning plan template. + * + * @param int $id the id of the learning plan template to duplicate + * @return boolean Record of new template. + */ + public static function duplicate_template($id) { + $params = self::validate_parameters(self::duplicate_template_parameters(), + array( + 'id' => $id, + )); + + $result = api::duplicate_template($params['id']); + return $result->to_record(); + } + + /** + * Returns description of duplicate_template() result value. + * + * @return \external_description + */ + public static function duplicate_template_returns() { + return self::get_template_external_structure(); + } + /** * Returns description of list_templates() parameters. * diff --git a/admin/tool/lp/db/services.php b/admin/tool/lp/db/services.php index 0d054e68546..254ef53d3eb 100644 --- a/admin/tool/lp/db/services.php +++ b/admin/tool/lp/db/services.php @@ -276,6 +276,14 @@ $functions = array( 'type' => 'write', 'capabilities' => 'tool/lp:templatemanage', ), + 'tool_lp_duplicate_template' => array( + 'classname' => 'tool_lp\external', + 'methodname' => 'duplicate_template', + 'classpath' => '', + 'description' => 'Duplicate learning plan template.', + 'type' => 'write', + 'capabilities' => 'tool/lp:templatemanage', + ), 'tool_lp_read_template' => array( 'classname' => 'tool_lp\external', 'methodname' => 'read_template', diff --git a/admin/tool/lp/lang/en/tool_lp.php b/admin/tool/lp/lang/en/tool_lp.php index b547d9666df..fdcbea53446 100644 --- a/admin/tool/lp/lang/en/tool_lp.php +++ b/admin/tool/lp/lang/en/tool_lp.php @@ -52,6 +52,7 @@ $string['deletethisplan'] = 'Delete this learning plan'; $string['description'] = 'Description'; $string['duedate'] = 'Due date'; $string['duedate_help'] = 'The date that a learning plan should be completed by.'; +$string['duplicateditemname'] = '{$a} (copy)'; $string['editcompetency'] = 'Edit competency'; $string['editcompetencyframework'] = 'Edit competency framework'; $string['editplan'] = 'Edit learning plan'; diff --git a/admin/tool/lp/templates/manage_templates_page.mustache b/admin/tool/lp/templates/manage_templates_page.mustache index eb78750eca3..208851b5cf7 100644 --- a/admin/tool/lp/templates/manage_templates_page.mustache +++ b/admin/tool/lp/templates/manage_templates_page.mustache @@ -57,6 +57,11 @@ {{#pix}}t/edit{{/pix}} {{#str}}edit{{/str}} +
  • + + {{#pix}}t/copy{{/pix}} {{#str}}duplicate{{/str}} + +
  • {{#pix}}t/delete{{/pix}} {{#str}}delete{{/str}} @@ -85,14 +90,15 @@ {{#js}} // Initialise the JS. -require(['tool_lp/templatedelete', +require(['tool_lp/templateactions', 'tool_lp/menubar'], - function(deleteMod, menubar) { + function(actionsMod, menubar) { - deleteMod.init({{pagecontextid}}); + actionsMod.init({{pagecontextid}}); menubar.enhance('.templateactions', { - '[data-action="deletetemplate"]': deleteMod.deleteHandler + '[data-action="deletetemplate"]': actionsMod.deleteHandler, + '[data-action="duplicatetemplate"]': actionsMod.duplicateHandler }); }); diff --git a/admin/tool/lp/tests/externallib_test.php b/admin/tool/lp/tests/externallib_test.php index 9cc964fe55c..7d2495f0927 100644 --- a/admin/tool/lp/tests/externallib_test.php +++ b/admin/tool/lp/tests/externallib_test.php @@ -1314,6 +1314,50 @@ class tool_lp_external_testcase extends externallib_advanced_testcase { external::reorder_template_competency($template->id, $competency1->id, $competency2->id); } + /** + * Test we can duplicate learning plan template. + */ + public function test_duplicate_learning_plan_template() { + $this->setUser($this->creator); + + $syscontext = context_system::instance(); + + // Create a template. + $template = external::create_template('shortname', 'idnumber', time(), 'description', FORMAT_HTML, true, + array('contextid' => $syscontext->id)); + $template = (object) external_api::clean_returnvalue(external::create_template_returns(), $template); + + // Create a competency framework. + $framework = external::create_competency_framework('shortname', 'idnumber', 'description', FORMAT_HTML, 1, + $this->scaleconfiguration1, true, array('contextid' => context_system::instance()->id)); + $framework = (object) external_api::clean_returnvalue(external::create_competency_framework_returns(), $framework); + + // Create multiple competencies. + $competency1 = external::create_competency('shortname1', 'idnumber1', 'description', FORMAT_HTML, true, $framework->id, 0); + $competency1 = (object) external_api::clean_returnvalue(external::create_competency_returns(), $competency1); + $competency2 = external::create_competency('shortname2', 'idnumber2', 'description', FORMAT_HTML, true, $framework->id, 0); + $competency2 = (object) external_api::clean_returnvalue(external::create_competency_returns(), $competency2); + $competency3 = external::create_competency('shortname3', 'idnumber3', 'description', FORMAT_HTML, true, $framework->id, 0); + $competency3 = (object) external_api::clean_returnvalue(external::create_competency_returns(), $competency3); + + // Add the competencies. + external::add_competency_to_template($template->id, $competency1->id); + external::add_competency_to_template($template->id, $competency2->id); + external::add_competency_to_template($template->id, $competency3->id); + + // Duplicate the learning plan template. + $duplicatedtemplate = external::duplicate_template($template->id); + + $result = external::list_competencies_in_template($template->id); + $resultduplicated = external::list_competencies_in_template($duplicatedtemplate->id); + + $this->assertEquals(count($result), count($resultduplicated)); + $this->assertContains($template->shortname, $duplicatedtemplate->shortname); + $this->assertEquals($duplicatedtemplate->description, $template->description); + $this->assertEquals($duplicatedtemplate->descriptionformat, $template->descriptionformat); + $this->assertEquals($duplicatedtemplate->visible, $template->visible); + } + /** * Test that we can return scale values for a scale with the scale ID. */