diff --git a/app/assets/javascripts/projects/canvas.js b/app/assets/javascripts/projects/canvas.js index a34355e13..4538f0cde 100644 --- a/app/assets/javascripts/projects/canvas.js +++ b/app/assets/javascripts/projects/canvas.js @@ -227,6 +227,9 @@ function initializeEdit() { if (canMoveModules) { initMoveModules(); $(".move-module").on("click touchstart", moveModuleHandler); + + initMoveModuleGroups(); + $(".move-module-group").on("click touchstart", moveModuleGroupHandler); } if (canDeleteModules) { bindDeleteModuleAction(); @@ -254,6 +257,7 @@ function destroyEdit() { // Read permissions from the data attributes of the form var canCreateModules = _.isEqual($("#update-canvas").data("can-create-modules"), "yes"); var canCloneModules = _.isEqual($("#update-canvas").data("can-clone-modules"), "yes"); + var canMoveModules = _.isEqual($("#update-canvas").data("can-move-modules"), "yes"); var canDeleteModules = _.isEqual($("#update-canvas").data("can-delete-modules"), "yes"); instance.cleanupListeners(); @@ -281,6 +285,9 @@ function destroyEdit() { $(".buttons-container a.clone-module").off("click touchstart"); $(".buttons-container a.clone-module-group").off("click touchstart"); } + if (canMoveModules) { + $(".move-module").off("click touchstart"); + } $("#update-canvas .cancel-edit-canvas").off("click"); $(window).off("beforeunload"); @@ -1838,7 +1845,7 @@ function initMoveModules() { // Add this information to form var formMoveInput = $("#update-canvas form input#move"); - // Actually rename an existing module + // Save mapping to input var moveVal = JSON.parse(formMoveInput.attr("value")); moveVal[moduleEl.attr("id")] = moveToExperimentId; formMoveInput.attr("value", JSON.stringify(moveVal)); @@ -1907,6 +1914,96 @@ moveModuleHandler = function(ev) { return false; }; + +/** + * Initialize editing of module groups. + */ +function initMoveModuleGroups() { + function handleMoveModuleGroupConfirm(modal) { + var moduleId = modal.attr("data-module-id"); + var moduleEl = $("#" + moduleId); + var input = modal.find('.selectpicker'); + var moveToExperimentId = input.val(); + + // Retrieve all modules in this module group + var components = connectedComponents(graph, moduleId.toString()); + var group = _.map(components, function(id) { return $("#" + id); }); + + // Add this information to form + var formMoveInput = $("#update-canvas form input#move"); + + moveModules = []; + _.each(group, function(m) { + moveModules.push(m.attr("id")); + deleteModule(m.attr("id")); + }); + + // Put the array into input + var moveVal = JSON.parse(formMoveInput.attr("value")); + moveVal[moveModules] = moveToExperimentId; + formMoveInput.attr("value", JSON.stringify(moveVal)); + + // Hide modal + modal.modal("hide"); + } + + $("#modal-move-module-group") + .on("show.bs.modal", function (event) { + var modal = $(this); + var moduleId = modal.attr("data-module-id"); + var moduleEl = $("#" + moduleId); + var input = modal.find('.selectpicker'); + + // Bind on enter button + input.keydown(function(ev) { + if (ev.keyCode == 13) { + // "Submit" modal + handleMoveConfirm(modal); + + // In any case, prevent form submission + ev.preventDefault(); + ev.stopPropagation(); + return false; + } + }); + }) + .on("shown.bs.modal", function(event) { + // Focus the text element + $(this).find(".selectpicker").focus(); + }) + .on("hide.bs.modal", function (event) { + // When hiding modal, re-enable events + toggleCanvasEvents(true); + }); + + // Bind the confirm button on modal + $("#modal-move-module-group").find("button[data-action='confirm']").on("click", function(event) { + var modal = $(this).closest(".modal"); + handleMoveModuleGroupConfirm(modal); + }); +} + +/** + * Handler when editing a module group. + */ +moveModuleGroupHandler = function(ev) { + var modal = $("#modal-move-module-group"); + var moduleEl = $(this).closest(".module"); + + // Set modal's module id + modal.attr("data-module-id", moduleEl.attr("id")); + + // Disable dragging & zooming events on canvas temporarily + toggleCanvasEvents(false); + + // Show modal + modal.modal("show"); + + ev.preventDefault(); + ev.stopPropagation(); + return false; +}; + /** * Bind the delete module buttons actions. */ diff --git a/app/views/canvas/_edit.html.erb b/app/views/canvas/_edit.html.erb index a5bc39639..855fb6739 100644 --- a/app/views/canvas/_edit.html.erb +++ b/app/views/canvas/_edit.html.erb @@ -86,6 +86,7 @@ <% end %> <% if can_move_modules(@experiment) %> <%= render partial: "canvas/edit/modal/move_module", locals: {experiment: @experiment } %> + <%= render partial: "canvas/edit/modal/move_module_group", locals: {experiment: @experiment } %> <% end %> <% if can_archive_modules(@experiment) %> <%= render partial: "canvas/edit/modal/delete_module", locals: {experiment: @experiment} %> diff --git a/app/views/canvas/edit/_my_module.html.erb b/app/views/canvas/edit/_my_module.html.erb index 102dbad84..11dd160c2 100644 --- a/app/views/canvas/edit/_my_module.html.erb +++ b/app/views/canvas/edit/_my_module.html.erb @@ -43,6 +43,9 @@
  • <%=t "experiments.canvas.edit.move_module" %>
  • +
  • > + <%=t "experiments.canvas.edit.move_module_group" %> +
  • <% end %> <% if can_archive_module(my_module) %>
  • diff --git a/app/views/canvas/edit/modal/_move_module_group.html.erb b/app/views/canvas/edit/modal/_move_module_group.html.erb new file mode 100644 index 000000000..2f9aae21f --- /dev/null +++ b/app/views/canvas/edit/modal/_move_module_group.html.erb @@ -0,0 +1,22 @@ + diff --git a/config/locales/en.yml b/config/locales/en.yml index 51bf7b048..ef8e6fd82 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -658,6 +658,7 @@ en: clone_module: "Clone task" clone_module_group: "Clone workflow" move_module: "Move task to another experiment" + move_module_group: "Move workflow to another experiment" delete_module: "Archive task" delete_module_group: "Archive workflow" modal_new_module: @@ -678,8 +679,10 @@ en: confirm: "Rename workflow" modal_move_module: title: "Move task to experiment" - name: "Task name" confirm: "Move task" + modal_move_module_group: + title: "Move workflow to experiment" + confirm: "Move workflow" modal_delete_module: title: "Archive task" confirm: "Archive task"