Merge pull request #16524 from mauriciofauth/jquery-ui-dialog

Replace jQuery UI dialog with Bootstrap's modal
This commit is contained in:
Maurício Meneghini Fauth 2021-01-12 17:37:36 -03:00 committed by GitHub
commit 71690531af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 201 additions and 263 deletions

View File

@ -185,36 +185,9 @@ DatabaseStructure.fetchRealRowCount = function ($target) {
};
AJAX.registerOnload('database/structure.js', function () {
/**
* function to open the confirmation dialog for making table consistent with central list
*
* @param string msg message text to be displayed to user
* @param function success function to be called on success
*
*/
var jqConfirm = function (msg, success) {
var dialogObj = $('<div class=\'hide\'>' + msg + '</div>');
$('body').append(dialogObj);
var buttonOptions = {};
buttonOptions[Messages.strContinue] = function () {
success();
$(this).dialog('close');
};
buttonOptions[Messages.strCancel] = function () {
$(this).dialog('close');
$('#tablesForm')[0].reset();
};
$(dialogObj).dialog({
resizable: false,
modal: true,
title: Messages.confirmTitle,
buttons: buttonOptions
});
};
/**
* Event handler on select of "Make consistent with central list"
*/
* Event handler on select of "Make consistent with central list"
*/
$('select[name=submit_mult]').on('change', function (event) {
var url = 'index.php?route=/database/structure';
var action = $(this).val();
@ -222,12 +195,12 @@ AJAX.registerOnload('database/structure.js', function () {
if (action === 'make_consistent_with_central_list') {
event.preventDefault();
event.stopPropagation();
jqConfirm(
Messages.makeConsistentMessage,
function () {
var $form = $('#tablesForm');
var argsep = CommonParams.get('arg_separator');
var data = $form.serialize() + argsep + 'ajax_request=true' + argsep + 'ajax_page_request=true';
$('#makeConsistentWithCentralListModal').modal('show').on('shown.bs.modal', function () {
$('#makeConsistentWithCentralListContinue').on('click', function () {
const $form = $('#tablesForm');
const argSep = CommonParams.get('arg_separator');
const data = $form.serialize() + argSep + 'ajax_request=true' + argSep + 'ajax_page_request=true';
Functions.ajaxShowMessage();
AJAX.source = $form;
@ -237,9 +210,12 @@ AJAX.registerOnload('database/structure.js', function () {
data,
AJAX.responseHandler
);
}
);
return false;
$('#makeConsistentWithCentralListModal').modal('hide');
});
});
return;
}
if (action === 'copy_tbl' ||
@ -272,25 +248,17 @@ AJAX.registerOnload('database/structure.js', function () {
url: url,
dataType: 'html',
data: formData
}).done(function (data) {
var dialogObj = $('<div class=\'hide\'>' + data + '</div>');
$('body').append(dialogObj);
var buttonOptions = {};
buttonOptions[Messages.strContinue] = function () {
$('#ajax_form').trigger('submit');
$(this).dialog('close');
};
buttonOptions[Messages.strCancel] = function () {
$(this).dialog('close');
$('#tablesForm')[0].reset();
};
$(dialogObj).dialog({
minWidth: 500,
resizable: false,
modal: true,
title: modalTitle,
buttons: buttonOptions
}).done(function (modalBody) {
const bulkActionModal = $('#bulkActionModal');
bulkActionModal.on('show.bs.modal', function () {
this.querySelector('.modal-title').innerText = modalTitle;
this.querySelector('.modal-body').innerHTML = modalBody;
});
bulkActionModal.modal('show').on('shown.bs.modal', function () {
$('#bulkActionContinue').on('click', function () {
$('#ajax_form').trigger('submit');
$('#bulkActionModal').modal('hide');
});
});
});

View File

@ -61,57 +61,31 @@ var ErrorReport = {
* @return void
*/
showReportDialog: function (exception) {
var reportData = ErrorReport.getReportData(exception);
const reportData = ErrorReport.getReportData(exception);
/* Remove the hidden dialogs if there are*/
if ($('#error_report_dialog').length !== 0) {
$('#error_report_dialog').remove();
}
var $div = $('<div id="error_report_dialog"></div>');
$div.css('z-index', '1000');
var buttonOptions = {};
buttonOptions[Messages.strSendErrorReport] = function () {
var $dialog = $(this);
var postData = $.extend(reportData, {
const sendErrorReport = function () {
const postData = $.extend(reportData, {
'send_error_report': true,
'description': $('#report_description').val(),
'always_send': $('#always_send_checkbox')[0].checked
'description': $('#errorReportDescription').val(),
'always_send': $('#errorReportAlwaysSendCheckbox')[0].checked
});
$.post('index.php?route=/error-report', postData, function (data) {
$dialog.dialog('close');
if (data.success === false) {
// in the case of an error, show the error message returned.
Functions.ajaxShowMessage(data.error, false);
} else {
Functions.ajaxShowMessage(data.message, 3000);
}
});
$('#errorReportModal').modal('hide');
};
buttonOptions[Messages.strCancel] = function () {
$(this).dialog('close');
};
$.post('index.php?route=/error-report', reportData, function (data) {
if (data.success === false) {
// in the case of an error, show the error message returned.
Functions.ajaxShowMessage(data.error, false);
} else {
// Show dialog if the request was successful
$div
.append(data.message)
.dialog({
title: Messages.strSubmitErrorReport,
width: 650,
modal: true,
buttons: buttonOptions,
close: function () {
$(this).remove();
}
});
}
$.post('index.php?route=/error-report', reportData).done(function (data) {
const $errorReportModal = $('#errorReportModal');
$errorReportModal.on('show.bs.modal', function () {
$('#errorReportModalConfirm').on('click', sendErrorReport);
this.querySelector('.modal-body').innerHTML = data.message;
});
$errorReportModal.modal('show');
});
},
/**

View File

@ -3,47 +3,41 @@
* @name Server User Groups
*
* @requires jQuery
* @requires jQueryUI
*/
/**
* Unbind all event handlers before tearing down a page
*/
AJAX.registerTeardown('server/user_groups.js', function () {
$(document).off('click', 'a.deleteUserGroup.ajax');
$('#deleteUserGroupModal').off('show.bs.modal');
});
/**
* Bind event handlers
*/
AJAX.registerOnload('server/user_groups.js', function () {
// update the checkall checkbox on Edit user group page
$(Functions.checkboxesSel).trigger('change');
const deleteUserGroupModal = $('#deleteUserGroupModal');
deleteUserGroupModal.on('show.bs.modal', function (event) {
const userGroupName = $(event.relatedTarget).data('user-group');
this.querySelector('.modal-body').innerText = Functions.sprintf(
Messages.strDropUserGroupWarning,
Functions.escapeHtml(userGroupName)
);
});
deleteUserGroupModal.on('shown.bs.modal', function (event) {
const userGroupName = $(event.relatedTarget).data('user-group');
$('#deleteUserGroupConfirm').on('click', function () {
$.post(
'index.php?route=/server/user-groups',
{
'deleteUserGroup': true,
'userGroup': userGroupName,
'ajax_request': true,
},
AJAX.responseHandler
);
$(document).on('click', 'a.deleteUserGroup.ajax', function (event) {
event.preventDefault();
var $link = $(this);
var groupName = $link.parents('tr').find('td').first().text();
var buttonOptions = {};
buttonOptions[Messages.strGo] = function () {
$(this).dialog('close');
$link.removeClass('ajax').trigger('click');
};
buttonOptions[Messages.strClose] = function () {
$(this).dialog('close');
};
$('<div></div>')
.attr('id', 'confirmUserGroupDeleteDialog')
.append(Functions.sprintf(Messages.strDropUserGroupWarning, Functions.escapeHtml(groupName)))
.dialog({
width: 300,
minWidth: 200,
modal: true,
buttons: buttonOptions,
title: Messages.strConfirm,
close: function () {
$(this).remove();
}
});
$('#deleteUserGroupModal').modal('hide');
});
});
});

View File

@ -405,12 +405,6 @@ final class JavaScriptMessagesController
. 'database %s has columns that are not present in the current table.'
),
'seeMore' => __('See more'),
'confirmTitle' => __('Are you sure?'),
'makeConsistentMessage' => __(
'This action may change some of the columns definition.<br>Are you sure you '
. 'want to continue?'
),
'strContinue' => __('Continue'),
/** For normalization */
'strAddPrimaryKey' => __('Add primary key'),
@ -635,8 +629,6 @@ final class JavaScriptMessagesController
'strCreateView' => __('Create view'),
/* Error Reporting */
'strSendErrorReport' => __('Send error report'),
'strSubmitErrorReport' => __('Submit error report'),
'strErrorOccurred' => __(
'A fatal JavaScript error has occurred. Would you like to send an error report?'
),

View File

@ -385,8 +385,8 @@ class ErrorHandler
. __('Report')
. '" id="pma_report_errors" class="btn btn-primary float-end">'
. '<input type="checkbox" name="always_send"'
. ' id="always_send_checkbox" value="true">'
. '<label for="always_send_checkbox">'
. ' id="errorReportAlwaysSendCheckbox" value="true">'
. '<label for="errorReportAlwaysSendCheckbox">'
. __('Automatically send report next time')
. '</label>';

View File

@ -6,8 +6,6 @@ namespace PhpMyAdmin;
use PhpMyAdmin\Utils\HttpRequest;
use const E_USER_WARNING;
use const JSON_PRETTY_PRINT;
use const JSON_UNESCAPED_SLASHES;
use const PHP_VERSION;
use function count;
use function http_build_query;
@ -63,20 +61,6 @@ class ErrorReport
$this->submissionUrl = $submissionUrl;
}
/**
* Returns the pretty printed error report data collected from the
* current configuration or from the request parameters sent by the
* error reporting js code.
*
* @return string the report
*/
private function getPrettyData(): string
{
$report = $this->getData();
return json_encode($report, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
}
/**
* Returns the error report data collected from the current configuration or
* from the request parameters sent by the error reporting js code.
@ -289,13 +273,14 @@ class ErrorReport
*/
public function getForm(): string
{
$reportData = $this->getData();
$datas = [
'report_data' => $this->getPrettyData(),
'report_data' => $reportData,
'hidden_inputs' => Url::getHiddenInputs(),
'hidden_fields' => null,
];
$reportData = $this->getData();
if (! empty($reportData)) {
$datas['hidden_fields'] = Url::getHiddenFields($reportData, '', true);
}

View File

@ -369,6 +369,7 @@ class Footer
'is_demo' => $GLOBALS['cfg']['DBG']['demo'],
'demo_message' => $demoMessage ?? '',
'footer' => $footer ?? '',
'has_error_report_modal' => $GLOBALS['cfg']['SendErrorReports'] !== 'never',
]);
}

View File

@ -123,15 +123,6 @@ class UserGroups
''
);
$userGroupVal['editUsersIcon'] = Generator::getIcon('b_edit', __('Edit'));
$userGroupVal['deleteUsersUrl'] = Url::getCommon(
[
'deleteUserGroup' => 1,
'userGroup' => $groupName,
],
''
);
$userGroupVal['deleteUsersIcon'] = Generator::getIcon('b_drop', __('Delete'));
$userGroupsValues[] = $userGroupVal;
}
}

View File

@ -555,11 +555,6 @@ parameters:
count: 1
path: libraries/classes/ErrorHandler.php
-
message: "#^Method PhpMyAdmin\\\\ErrorReport\\:\\:getPrettyData\\(\\) should return string but returns string\\|false\\.$#"
count: 1
path: libraries/classes/ErrorReport.php
-
message: "#^Strict comparison using \\=\\=\\= between string and null will always evaluate to false\\.$#"
count: 1

View File

@ -38,3 +38,41 @@
</select>
{{ hidden_fields|join('\n')|raw }}
</div>
<div class="modal fade" id="bulkActionModal" data-bs-backdrop="static" data-bs-keyboard="false"
tabindex="-1" aria-labelledby="bulkActionLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="bulkActionLabel"></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{% trans 'Cancel' %}"></button>
</div>
<div class="modal-body"></div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{% trans 'Cancel' %}</button>
<button type="button" class="btn btn-primary" id="bulkActionContinue">{% trans 'Continue' %}</button>
</div>
</div>
</div>
</div>
{% if central_columns_work is defined and central_columns_work %}
<div class="modal fade" id="makeConsistentWithCentralListModal" data-bs-backdrop="static" data-bs-keyboard="false"
tabindex="-1" aria-labelledby="makeConsistentWithCentralListModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="makeConsistentWithCentralListModalLabel">{% trans 'Are you sure?' %}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{% trans 'Cancel' %}"></button>
</div>
<div class="modal-body">
{{ 'This action may change some of the columns definition.[br]Are you sure you want to continue?'|trans|sanitize }}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{% trans 'Cancel' %}</button>
<button type="button" class="btn btn-primary" id="makeConsistentWithCentralListContinue">{% trans 'Continue' %}</button>
</div>
</div>
</div>
</div>
{% endif %}

View File

@ -1,31 +1,30 @@
<form action="{{ url('/error-report') }}" method="post" name="report_frm" id="report_frm"
class="ajax">
<fieldset class="pma-fieldset pt-0">
<p>
{% trans %}
This report automatically includes data about the error and information about relevant configuration settings. It will be sent to the phpMyAdmin team for debugging the error.
{% endtrans %}
</p>
<p>
{% trans %}
This report automatically includes data about the error and information about relevant configuration settings. It will be sent to the phpMyAdmin team for debugging the error.
{% endtrans %}
</p>
<form action="{{ url('/error-report') }}" method="post" id="errorReportForm" class="ajax">
<div class="mb-3">
<label for="errorReportDescription">
<strong>
{% trans "Can you tell us the steps leading to this error? It decisively helps in debugging:" %}
</strong>
</label>
<textarea class="form-control" name="description" id="errorReportDescription"></textarea>
</div>
<div class="label"><label><strong>
{% trans "Can you tell us the steps leading to this error? It decisively helps in debugging:" %}
</strong></label>
</div>
<textarea class="report-description" name="description"
id="report_description"></textarea>
<div class="mb-3">
{% trans "You may examine the data in the error report:" %}
<pre class="pre-scrollable">{{ report_data|json_encode(constant('JSON_PRETTY_PRINT') b-or constant('JSON_UNESCAPED_SLASHES')) }}</pre>
</div>
<div class="label"><label><p>
{% trans "You may examine the data in the error report:" %}
</p></label></div>
<pre class="report-data">{{ report_data|raw }}</pre>
<div class="form-check">
<input class="form-check-input" type="checkbox" name="always_send" id="errorReportAlwaysSendCheckbox">
<label class="form-check-label" for="errorReportAlwaysSendCheckbox">
{% trans "Automatically send report next time" %}
</label>
</div>
<input type="checkbox" name="always_send" id="always_send_checkbox">
<label for="always_send_checkbox">
{% trans "Automatically send report next time" %}
</label>
</fieldset>
{{ hidden_inputs|raw }}
{{ hidden_fields|raw }}
{{ hidden_inputs|raw }}
{{ hidden_fields|raw }}
</form>

View File

@ -16,6 +16,24 @@
</div>
{% endif %}
{% if has_error_report_modal %}
<div class="modal fade" id="errorReportModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="errorReportModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-scrollable modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="errorReportModalLabel">{% trans 'Submit error report' %}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{% trans 'Cancel' %}"></button>
</div>
<div class="modal-body"></div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{% trans 'Cancel' %}</button>
<button type="button" class="btn btn-primary" id="errorReportModalConfirm">{% trans 'Send error report' %}</button>
</div>
</div>
</div>
</div>
{% endif %}
{{ footer|raw }}
{% endif %}
{% if not is_ajax %}

View File

@ -33,14 +33,31 @@
<a class="" href="{{ groupName.userGroupUrl|raw }}" data-post="{{ groupName.viewUsersUrl|raw }}">{{ groupName.viewUsersIcon|raw }}</a>
&nbsp;&nbsp;
<a class="" href="{{ groupName.userGroupUrl|raw }}" data-post="{{ groupName.editUsersUrl|raw }}">{{ groupName.editUsersIcon|raw }}</a>
&nbsp;&nbsp;
<a class="deleteUserGroup ajax" href="{{ groupName.userGroupUrl|raw }}" data-post="{{ groupName.deleteUsersUrl|raw }}">{{ groupName.deleteUsersIcon|raw }}</a>
<button type="button" class="btn btn-link" data-bs-toggle="modal" data-bs-target="#deleteUserGroupModal" data-user-group="{{ groupName.name }}">
{{ get_icon('b_drop', 'Delete'|trans) }}
</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</form>
<div class="modal fade" id="deleteUserGroupModal" tabindex="-1" aria-labelledby="deleteUserGroupModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="deleteUserGroupModalLabel">{% trans 'Delete user group' %}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{% trans 'Close' %}"></button>
</div>
<div class="modal-body"></div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{% trans 'Close' %}</button>
<button type="button" class="btn btn-danger" id="deleteUserGroupConfirm">{% trans 'Delete' %}</button>
</div>
</div>
</div>
</div>
{% endif %}
<div class="row">
<fieldset class="pma-fieldset" id="fieldset_add_user_group">

View File

@ -9,6 +9,8 @@ use PhpMyAdmin\ErrorReport;
use PhpMyAdmin\Relation;
use PhpMyAdmin\Template;
use PhpMyAdmin\Utils\HttpRequest;
use function htmlspecialchars;
use const ENT_QUOTES;
use const JSON_PRETTY_PRINT;
use const JSON_UNESCAPED_SLASHES;
use function define;
@ -140,7 +142,7 @@ class ErrorReportTest extends AbstractTestCase
$_POST['exception'] = [];
$form = $this->errorReport->getForm();
$this->assertStringContainsString('<pre class="report-data">[]</pre>', $form);
$this->assertStringContainsString('<pre class="pre-scrollable">[]</pre>', $form);
$context = [
'Widget.prototype = {',
@ -207,7 +209,10 @@ class ErrorReportTest extends AbstractTestCase
$expectedData = json_encode($report, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
$form = $this->errorReport->getForm();
$this->assertStringContainsString('<pre class="report-data">' . $expectedData . '</pre>', $form);
$this->assertStringContainsString(
'<pre class="pre-scrollable">' . htmlspecialchars((string) $expectedData, ENT_QUOTES) . '</pre>',
$form
);
}
/**

View File

@ -136,16 +136,9 @@ class UserGroupsTest extends AbstractTestCase
$url_tag,
$html
);
$url_tag = '<a class="deleteUserGroup ajax" href="' . Url::getFromRoute('/server/user-groups') . '" data-post="'
. Url::getCommon(
[
'deleteUserGroup' => 1,
'userGroup' => htmlspecialchars('usergroup'),
],
''
);
$this->assertStringContainsString(
$url_tag,
'<button type="button" class="btn btn-link" data-bs-toggle="modal"'
. ' data-bs-target="#deleteUserGroupModal" data-user-group="usergroup">',
$html
);
}

View File

@ -2266,20 +2266,6 @@ body .ui-widget {
overflow: hidden;
}
.report-data {
height: 13em;
overflow: scroll;
width: 570px;
border: solid 1px;
background: white;
padding: 2px;
}
.report-description {
height: 10em;
width: 570px;
}
div#page_content div {
&#tableslistcontainer {
margin-top: 1em;
@ -3068,6 +3054,12 @@ body .ui-dialog {
overflow: hidden;
}
// Enable scrollable blocks of code
.pre-scrollable {
max-height: 340px;
overflow-y: scroll;
}
@media only screen and (max-width: 768px) {
.responsivetable {
overflow-x: auto;

View File

@ -2516,20 +2516,6 @@ body #ui-datepicker-div {
color: #235a81;
}
.report-data {
height: 13em;
overflow: scroll;
width: 570px;
border: solid 1px;
background: white;
padding: 2px;
}
.report-description {
height: 10em;
width: 570px;
}
div#page_content div {
&#tableslistcontainer {
margin-top: 1em;
@ -3376,6 +3362,12 @@ body {
}
}
// Enable scrollable blocks of code
.pre-scrollable {
max-height: 340px;
overflow-y: scroll;
}
// Extra large devices (large desktops, 1200px and up)
@include media-breakpoint-up(xl) {
div.tools {

View File

@ -2212,20 +2212,6 @@ body #ui-datepicker-div {
}
}
.report-data {
height: 13em;
overflow: scroll;
width: 570px;
border: solid 1px;
background: white;
padding: 2px;
}
.report-description {
height: 10em;
width: 570px;
}
div#page_content div {
&#tableslistcontainer {
margin-top: 1em;
@ -3148,6 +3134,12 @@ body {
height: 0.75rem;
}
// Enable scrollable blocks of code
.pre-scrollable {
max-height: 340px;
overflow-y: scroll;
}
// Extra large devices (large desktops, 1200px and up)
@include media-breakpoint-up(xl) {
div.tools {

View File

@ -2477,20 +2477,6 @@ body #ui-datepicker-div {
overflow: hidden;
}
.report-data {
height: 13em;
overflow: scroll;
width: 570px;
border: solid 1px;
background: white;
padding: 2px;
}
.report-description {
height: 10em;
width: 570px;
}
div#page_content div {
&#tableslistcontainer {
margin-top: 1em;
@ -3360,6 +3346,12 @@ body .ui-dialog {
height: 0.75rem;
}
// Enable scrollable blocks of code
.pre-scrollable {
max-height: 340px;
overflow-y: scroll;
}
// Extra large devices (large desktops, 1200px and up)
@include media-breakpoint-up(xl) {
div.tools {