Skip to content
Snippets Groups Projects
Commit 5aa230e0 authored by Mingsong's avatar Mingsong
Browse files

Issue #3205538: Add (optional) confirmation dialog after drag&drop

parent f30124e2
No related branches found
No related tags found
No related merge requests found
......@@ -16,3 +16,6 @@ hierarchy_manager.hm_display_profile.*:
config:
type: text
label: 'Configuration'
confirm:
type: boolean
label: 'Confirm'
......@@ -17,6 +17,7 @@
const optionsJson = treeContainer.attr("options");
const dataURL = treeContainer.attr('data-source') + '&parent=0';
const updateURL = treeContainer.attr('url-update');
const confirm = treeContainer.attr("confirm");
let reload = true;
let rollback = false;
let themes = {
......@@ -103,61 +104,80 @@
const drupalMessages = new Drupal.Message();
if (!rollback) {
// Update the data on server side.
$.post(updateURL, {
keys: [movedNode.id],
target: data.position,
parent: parent,
old_parent: old_parent,
old_position: data.old_position
})
.done(function(response) {
if (response.result !== "success") {
alert("Server error:" + response.result);
rollback = true;
thisTree.move_node(movedNode, data.old_parent, data.old_position);
}
else {
if (parent === 0) {
var parentText = Drupal.t('root');
}
else {
var parentText = parent_node.text;
}
if (parent_node.data && !parent_node.data.draggable) {
// The parent node is not draggable.
// We have to update all duplicated nodes
// by refreshing the whole tree.
thisTree.refresh();
let parentText = Drupal.t('root');
if (parent !== 0) {
parentText = $("<div/>").html(thisTree.get_node(parent).text);
parentText.find("span").remove();
parentText = parentText.text();
}
// Function to move the tree item.
function moveTreeItem() {
// Update the data on server side.
$.post(updateURL, {
keys: [movedNode.id],
target: data.position,
parent: parent,
old_parent: old_parent,
old_position: data.old_position
})
.done(function(response) {
if (response.result !== "success") {
alert("Server error:" + response.result);
rollback = true;
thisTree.move_node(movedNode, data.old_parent, data.old_position);
}
else {
// Update the nodes changed in the server side.
if (response.updated_nodes) {
let update_nodes = response.updated_nodes;
for (const id in update_nodes) {
let node = thisTree.get_node(id);
if (node) {
node.data.weight = update_nodes[id];
if (parent_node.data && !parent_node.data.draggable) {
// The parent node is not draggable.
// We have to update all duplicated nodes
// by refreshing the whole tree.
thisTree.refresh();
}
else {
// Update the nodes changed in the server side.
if (response.updated_nodes) {
let update_nodes = response.updated_nodes;
for (const id in update_nodes) {
let node = thisTree.get_node(id);
if (node) {
node.data.weight = update_nodes[id];
}
}
//Refresh the tree without reloading data from server.
thisTree.sort(parent_node, true);
thisTree.redraw(true);
}
//Refresh the tree without reloading data from server.
thisTree.sort(parent_node, true);
thisTree.redraw(true);
}
let message = Drupal.t('@node is moved to position @position under @parent', {'@node': data.node.text, '@parent': parentText, '@position': data.position + 1});
// Inform user the movement.
drupalMessages.clear();
drupalMessages.add(message);
}
let message = Drupal.t('@node is moved to position @position under @parent', {'@node': data.node.text, '@parent': parentText, '@position': data.position + 1});
// Inform user the movement.
})
.fail(function() {
drupalMessages.clear();
drupalMessages.add(message);
}
})
.fail(function() {
drupalMessages.clear();
drupalMessages.add(Drupal.t("Can't connect to the server."), {type: 'error'});
rollback = true;
thisTree.move_node(movedNode, data.old_parent, data.old_position);
});
drupalMessages.add(Drupal.t("Can't connect to the server."), {type: 'error'});
rollback = true;
thisTree.move_node(movedNode, data.old_parent, data.old_position);
});
}
// Check if confirmation dialog is enabled.
if (typeof confirm !== 'undefined' && confirm !== false) {
// Confirmation dialog enabled.
let modalTitle = Drupal.t('Confirm move?');
let modalMessage = Drupal.t('Move <em class="placeholder">@node</em> to position @position under <em class="placeholder">@parent</em>?', { '@node': data.node.text, '@parent': parentText, '@position': data.position + 1 });
modalConfirmation(modalTitle, modalMessage, moveTreeItem, function () {
// Callback when confirmation is denied.
rollback = true;
thisTree.move_node(movedNode, data.old_parent, data.old_position);
});
} else {
// Confirmation dialog disabled.
moveTreeItem()
}
}
else {
rollback = false;
......@@ -184,4 +204,51 @@
});
}
};
/**
* Generic modal helper function.
*
* @param {string} title - The title for the confirm dialog.
* @param {string} message - The main message for the confirm dialog.
* @param {function} accept - Callback fired when the user answers positive.
* @param {function} deny - Callback fired when the user answers negative.
* @returns {Object} - A jQuery dialog object.
*/
function modalConfirmation(title, message, accept, deny) {
let proceed = false;
let modalConfirmationForm = $('<div></div>').appendTo('body')
.html(message)
.dialog({
modal: true,
title: title,
autoOpen: false,
width: 400,
resizable: false,
sticky: true,
closeOnEscape: true,
dialogClass: "hm-confirm",
buttons: [
{
class: 'button button--primary',
text: Drupal.t('Yes'),
click: function () {
proceed = true;
$(this).dialog('close');
}
},
{
class: 'button',
text: Drupal.t('No'),
click: function () {
$(this).dialog('close');
}
}
],
close: function () {
proceed ? accept() : deny();
}
});
return modalConfirmationForm.dialog('open');
}
})(jQuery, Drupal);
......@@ -34,6 +34,7 @@ use Drupal\Core\Config\Entity\ConfigEntityBase;
* "label",
* "plugin",
* "config",
* "confirm",
* },
* links = {
* "canonical" = "/admin/structure/hm_display_profile/{hm_display_profile}",
......@@ -73,4 +74,11 @@ class HmDisplayProfile extends ConfigEntityBase implements HmDisplayProfileInter
* @var string
*/
protected $config;
/**
* The confirmation option.
*
* @var bool
*/
protected $confirm = FALSE;
}
......@@ -114,6 +114,13 @@ class HmDisplayProfileForm extends EntityForm {
];
}
$form['confirm'] = [
'#type' => 'checkbox',
'#title' => $this->t('Confirm drag&drop'),
'#default_value' => $hm_display_profile->get("confirm"),
'#description' => $this->t('Displays a dialog when changing the hierarchy.'),
];
return $form;
}
......@@ -132,6 +139,9 @@ class HmDisplayProfileForm extends EntityForm {
$hm_display_profile->set('config', $input['config']);
}
if (isset($input['confirm'])) {
$hm_display_profile->set('confirm', $input['confirm']);
}
$status = $hm_display_profile->save();
......
......@@ -98,7 +98,8 @@ class HmMenuForm extends MenuForm {
$source_url = Url::fromRoute('hierarchy_manager.menu.tree.json', ['mid' => $mid], ['query' => ['token' => $token, 'destination' => $destination]])->toString();
$update_url = Url::fromRoute('hierarchy_manager.menu.tree.update', ['mid' => $mid], ['query' => ['token' => $token]])->toString();
$config = $display_profile->get("config");
return $display_plugin_instance->getForm($source_url, $update_url, $form, $form_state, $config);
$confirm = $display_profile->get("confirm");
return $display_plugin_instance->getForm($source_url, $update_url, $form, $form_state, $config, $confirm);
}
}
......
......@@ -64,7 +64,8 @@ class HmOverviewTerms extends OverviewTerms {
$source_url = Url::fromRoute('hierarchy_manager.taxonomy.tree.json', ['vid' => $vid], ['query' => ['token' => $token, 'destination' => $destination]])->toString();
$update_url = Url::fromRoute('hierarchy_manager.taxonomy.tree.update', ['vid' => $vid], ['query' => ['token' => $token]])->toString();
$config = $display_profile->get("config");
return $instance->getForm($source_url, $update_url, $form, $form_state, $config);
$confirm = $display_profile->get('confirm');
return $instance->getForm($source_url, $update_url, $form, $form_state, $config, $confirm);
}
}
}
......
......@@ -23,7 +23,7 @@ class HmDisplayJstree extends HmDisplayPluginBase implements HmDisplayPluginInte
/*
* Build the tree form.
*/
public function getForm(string $url_source, string $url_update, array &$form = [], FormStateInterface &$form_state = NULL, $options = NULL) {
public function getForm(string $url_source, string $url_update, array &$form = [], FormStateInterface &$form_state = NULL, $options = NULL, $confirm = FALSE) {
if (!empty($url_source)) {
if (!empty(($form_state))) {
$parent_formObj = $form_state->getFormObject();
......@@ -70,6 +70,7 @@ class HmDisplayJstree extends HmDisplayPluginBase implements HmDisplayPluginInte
'id' => isset($parent_id) ? 'hm-jstree-' . $parent_id : 'hm-jstree',
'parent-id' => isset($parent_id) ? $parent_id : '',
'options' => $options,
'confirm' => $confirm,
'data-source' => $url_source,
'url-update' => $url_update,
],
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment