Merge pull request #19703 from MauricioFauth/jquery-ui-dialog-removal

Replace jQuery UI's dialog components with Bootstrap modal component
This commit is contained in:
Maurício Meneghini Fauth 2025-05-17 12:15:51 -03:00 committed by GitHub
commit b226aef1c4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 869 additions and 1017 deletions

View File

@ -508,8 +508,6 @@ div {
}
&#queryAnalyzerDialog {
min-width: 700px;
div {
&.CodeMirror-scroll {
height: auto;
@ -1552,10 +1550,6 @@ div#page_content div {
}
}
.ui-dialog {
position: fixed;
}
.small_font {
font-size: smaller;
}
@ -2276,34 +2270,6 @@ th {
// end of styles of sortable tables
// styles for jQuery-ui to support rtl languages
body .ui-dialog {
.ui-dialog-titlebar-close {
right: 0.3em;
left: initial;
}
.ui-dialog-title {
float: left;
}
.ui-dialog-buttonpane .ui-dialog-buttonset {
float: right;
}
.ui-dialog-buttonpane .ui-dialog-buttonset button {
color: $white;
background: none;
background-color: #6c757d !important;
border-color: #6c757d;
}
.ui-dialog-buttonpane .ui-dialog-buttonset button:hover {
background-color: #5a6268 !important;
}
}
// end of styles for jQuery-ui to support rtl languages
// templates/database/designer
// side menu
#name-panel {
@ -2352,11 +2318,6 @@ body .ui-dialog {
min-width: 100%;
}
}
.ui-dialog {
margin: 1%;
width: 95% !important;
}
}
#tooltip_editor {

View File

@ -761,8 +761,6 @@ div {
}
&#queryAnalyzerDialog {
min-width: 700px;
div {
&.CodeMirror-scroll {
height: auto;
@ -2470,21 +2468,6 @@ meter {
/* styles for jQuery-ui to support rtl languages */
body {
.ui-dialog {
.ui-dialog-titlebar-close {
right: 0.3em;
left: initial;
}
.ui-dialog-title {
float: left;
}
.ui-dialog-buttonpane .ui-dialog-buttonset {
float: right;
}
}
.ui-corner-all,
.ui-corner-top,
.ui-corner-left,
@ -2512,40 +2495,6 @@ body {
.ui-corner-br {
border-bottom-right-radius: 0;
}
.ui-dialog {
padding: 0;
.ui-widget-header {
color: $button-color;
border: none;
background-color: var(--navi-background);
background-image: none;
}
.ui-dialog-title {
padding: 5px;
font-weight: normal;
}
.ui-dialog-buttonpane button {
font-family: $font-family-base;
color: $button-color;
background-color: var(--navi-background);
background-image: none;
border: 1px solid var(--button-background);
&.ui-state-hover {
background-color: var(--button-hover);
border: 1px solid var(--button-hover);
}
&.ui-state-active {
background-color: #333;
border: 1px solid #333;
}
}
}
}
#tooltip_editor {

View File

@ -1584,10 +1584,6 @@ div#page_content div {
}
}
.ui-dialog {
position: fixed;
}
.small_font {
font-size: smaller;
}
@ -2227,21 +2223,6 @@ span.drag_icon {
/* styles for jQuery-ui to support rtl languages */
body {
.ui-dialog {
.ui-dialog-titlebar-close {
right: 0.3em;
left: initial;
}
.ui-dialog-title {
float: left;
}
.ui-dialog-buttonpane .ui-dialog-buttonset {
float: right;
}
}
.ui-corner-all,
.ui-corner-top,
.ui-corner-left,
@ -2269,40 +2250,6 @@ body {
.ui-corner-br {
border-bottom-right-radius: 0;
}
.ui-dialog {
padding: 0;
border-color: #000;
.ui-dialog-titlebar {
padding: 0.3em 0.5em;
border: none;
border-bottom: 1px solid #000;
button {
border: 1px solid #999;
}
}
.ui-dialog-content {
padding: 0.2em 0.4em;
}
.ui-dialog-buttonpane {
background: #d3dce3;
border-top: 1px solid #000;
button {
margin: 0.1em 0 0.1em 0.4em;
border: 1px solid #999;
color: #000;
}
}
.ui-button-text-only .ui-button-text {
padding: 0.2em 0.6em;
}
}
}
/* templates/database/designer */
@ -2349,11 +2296,6 @@ body {
}
}
.ui-dialog {
margin: 1%;
width: 95% !important;
}
#server-breadcrumb .item {
margin: 4px;
}

View File

@ -694,8 +694,6 @@ div {
}
&#queryAnalyzerDialog {
min-width: 700px;
div {
&.CodeMirror-scroll {
height: auto;
@ -1777,10 +1775,6 @@ div#page_content div {
}
}
.ui-dialog {
position: fixed;
}
.small_font {
font-size: smaller;
}
@ -2435,23 +2429,6 @@ meter {
// end of styles of sortable tables
// styles for jQuery-ui to support rtl languages
body .ui-dialog {
.ui-dialog-titlebar-close {
right: 0.3em;
left: initial;
}
.ui-dialog-title {
float: left;
}
.ui-dialog-buttonpane .ui-dialog-buttonset {
float: right;
}
}
// end of styles for jQuery-ui to support rtl languages
// templates/database/designer
// side menu
#name-panel {
@ -2494,11 +2471,6 @@ body .ui-dialog {
min-width: 100%;
}
}
.ui-dialog {
margin: 1%;
width: 95% !important;
}
}
#tooltip_editor {

View File

@ -15,11 +15,6 @@ AJAX.registerTeardown('database/events.js', function () {
});
const DatabaseEvents = {
/**
* @var $ajaxDialog Query object containing the reference to the
* dialog that contains the editor
*/
$ajaxDialog: null,
/**
* @var syntaxHiglighter Reference to the codemirror editor
*/
@ -112,41 +107,23 @@ const DatabaseEvents = {
}
ajaxRemoveMessage($msg);
/**
* @var buttonOptions Object containing options
* for jQueryUI dialog buttons
*/
var buttonOptions = {
[window.Messages.strClose]: {
text: window.Messages.strClose,
class: 'btn btn-primary',
click: function () {
$(this).dialog('close').remove();
},
},
};
/**
* Display the dialog to the user
*/
data.message = '<textarea cols="40" rows="15" class="w-100">' + data.message + '</textarea>';
var $ajaxDialog = $('<div>' + data.message + '</div>').dialog({
classes: {
'ui-dialog-titlebar-close': 'btn-close'
},
width: 500,
// @ts-ignore
buttons: buttonOptions,
title: data.title
const eventsExportTextarea = '<textarea id="eventsExportTextarea" cols="40" rows="15" class="form-control" aria-label="' + window.Messages.strEvent + '"></textarea>';
const eventsExportModal = document.getElementById('eventsExportModal');
eventsExportModal.addEventListener('shown.bs.modal', function () {
eventsExportModal.querySelector('.modal-title').textContent = data.title;
eventsExportModal.querySelector('.modal-body').innerHTML = eventsExportTextarea;
document.getElementById('eventsExportTextarea').textContent = data.message;
getSqlEditor($('#eventsExportTextarea'));
});
// Attach syntax highlighted editor to export dialog
/**
* @var $elm jQuery object containing the reference
* to the Export textarea.
*/
var $elm = $ajaxDialog.find('textarea');
getSqlEditor($elm);
} // end showExport()
}, // end exportDialog()
eventsExportModal.addEventListener('hidden.bs.modal', function () {
eventsExportModal.querySelector('.modal-body').innerHTML = eventsExportTextarea;
});
window.bootstrap.Modal.getOrCreateInstance(eventsExportModal).show();
}
},
editorDialog: function (isNew, $this) {
var that = this;
/**
@ -176,24 +153,10 @@ const DatabaseEvents = {
// We have successfully fetched the editor form
ajaxRemoveMessage($msg);
/**
* @var buttonOptions Object containing options
* for jQueryUI dialog buttons
*/
var buttonOptions = {
[window.Messages.strGo]: {
text: window.Messages.strGo,
class: 'btn btn-primary',
},
[window.Messages.strClose]: {
text: window.Messages.strClose,
class: 'btn btn-secondary',
},
};
// Now define the function that is called when
// the user presses the "Go" button
// @ts-ignore
buttonOptions[window.Messages.strGo].click = function () {
let isEditMode = false;
function eventsEditorModalSaveEventHandler () {
// Move the data from the codemirror editor back to the
// textarea, where it can be used in the form submission.
if (typeof window.CodeMirror !== 'undefined') {
@ -221,10 +184,10 @@ const DatabaseEvents = {
// Item created successfully
ajaxRemoveMessage($msg);
slidingMessage(data.message);
that.$ajaxDialog.dialog('close');
window.bootstrap.Modal.getOrCreateInstance('#eventsEditorModal').hide();
// If we are in 'edit' mode, we must
// remove the reference to the old row.
if (mode === 'edit' && $editRow !== null) {
if (isEditMode && $editRow !== null) {
$editRow.remove();
}
@ -317,75 +280,61 @@ const DatabaseEvents = {
}
Navigation.reload();
}); // end $.post()
} // end "if (that.validate())"
}; // end of function that handles the submission of the Editor
// @ts-ignore
buttonOptions[window.Messages.strClose].click = function () {
$(this).dialog('close');
};
/**
* Display the dialog to the user
*/
that.$ajaxDialog = $('<div id="rteDialog">' + data.message + '</div>').dialog({
classes: {
'ui-dialog-titlebar-close': 'btn-close'
},
height: 500,
width: '70%',
minWidth: 500,
// @ts-ignore
buttons: buttonOptions,
// Issue #15810 - use button titles for modals (eg: new procedure)
// Respect the order: title on href tag, href content, title sent in response
title: $this.attr('title') || $this.text() || $(data.title).text(),
modal: true,
open: function () {
$('#rteDialog').dialog('option', 'max-height', $(window).height());
if ($('#rteDialog').parents('.ui-dialog').height() > $(window).height()) {
$('#rteDialog').dialog('option', 'height', $(window).height());
}
$(this).find('input[name=item_name]').trigger('focus');
$(this).find('input.datefield').each(function () {
addDatepicker($(this).css('width', '95%'), 'date');
});
$(this).find('input.datetimefield').each(function () {
addDatepicker($(this).css('width', '95%'), 'datetime');
});
// @ts-ignore
$.datepicker.initialized = false;
},
close: function () {
$(this).remove();
}
});
/**
* @var mode Used to remember whether the editor is in
* "Edit" or "Add" mode
*/
var mode = 'add';
if ($('input[name=editor_process_edit]').length > 0) {
mode = 'edit';
}
// Attach syntax highlighted editor to the definition
/**
* @var elm jQuery object containing the reference to
* the Definition textarea.
*/
var $elm = $('textarea[name=item_definition]').last();
var linterOptions = {
editorType: 'event',
};
that.syntaxHiglighter = getSqlEditor($elm, {}, 'vertical', linterOptions);
window.codeMirrorEditor = that.syntaxHiglighter;
}); // end $.get()
const eventsEditorModal = document.getElementById('eventsEditorModal');
eventsEditorModal.addEventListener('shown.bs.modal', function () {
/**
* Issue #15810 - use button titles for modals (eg: new procedure)
* Respect the order: title on href tag, href content, title sent in response
*/
eventsEditorModal.querySelector('.modal-title').textContent = $this.attr('title') || $this.text() || $(data.title).text();
eventsEditorModal.querySelector('.modal-body').innerHTML = data.message;
const eventsEditorModalSaveButton = document.getElementById('eventsEditorModalSaveButton');
eventsEditorModalSaveButton?.addEventListener('click', eventsEditorModalSaveEventHandler);
$(this).find('input[name=item_name]').trigger('focus');
$(this).find('input.datefield').each(function () {
addDatepicker($(this).css('width', '95%'), 'date');
});
$(this).find('input.datetimefield').each(function () {
addDatepicker($(this).css('width', '95%'), 'datetime');
});
// @ts-ignore
$.datepicker.initialized = false;
if ($('input[name=editor_process_edit]').length > 0) {
isEditMode = true;
}
// Attach syntax highlighted editor to the definition
/**
* @var elm jQuery object containing the reference to
* the Definition textarea.
*/
var $elm = $('textarea[name=item_definition]').last();
var linterOptions = {
editorType: 'event',
};
that.syntaxHiglighter = getSqlEditor($elm, {}, 'vertical', linterOptions);
window.codeMirrorEditor = that.syntaxHiglighter;
});
eventsEditorModal.addEventListener('hidden.bs.modal', function () {
const eventsEditorModalSaveButton = document.getElementById('eventsEditorModalSaveButton');
eventsEditorModalSaveButton?.removeEventListener('click', eventsEditorModalSaveEventHandler);
document.getElementById('eventsEditorModal').querySelector('.modal-body').innerHTML = '<div class="spinner-border" role="status">' +
'<span class="visually-hidden">' + window.Messages.strLoading + '</span></div>';
});
window.bootstrap.Modal.getOrCreateInstance(eventsEditorModal).show();
});
},
dropDialog: function ($this) {
@ -561,9 +510,10 @@ const DatabaseEvents = {
* to an element that is being validated
*/
var $elm = null;
if (this.$ajaxDialog.find('select[name=item_type]').find(':selected').val() === 'RECURRING') {
const eventsEditorModal = $('#eventsEditorModal');
if (eventsEditorModal.find('select[name=item_type]').find(':selected').val() === 'RECURRING') {
// The interval field must not be empty for recurring events
$elm = this.$ajaxDialog.find('input[name=item_interval_value]');
$elm = eventsEditorModal.find('input[name=item_interval_value]');
if ($elm.val() === '') {
$elm.trigger('focus');
alert(window.Messages.strFormEmpty);
@ -572,7 +522,7 @@ const DatabaseEvents = {
}
} else {
// The execute_at field must not be empty for "once off" events
$elm = this.$ajaxDialog.find('input[name=item_execute_at]');
$elm = eventsEditorModal.find('input[name=item_execute_at]');
if ($elm.val() === '') {
$elm.trigger('focus');
alert(window.Messages.strFormEmpty);

View File

@ -176,7 +176,7 @@ const DatabaseRoutines = {
// Move the data from the codemirror editor back to the
// textarea, where it can be used in the form submission.
if (typeof window.CodeMirror !== 'undefined') {
that.syntaxHiglighter?.save();
that.syntaxHiglighter.save();
}
// Validate editor and submit request, if passed.

View File

@ -825,7 +825,6 @@ function createAliasModal (event): void {
var modal = $('#renameExportModal');
modal.modal('show');
modal.on('shown.bs.modal', function () {
modal.closest('.ui-dialog').find('.ui-button').addClass('btn btn-secondary');
var db = CommonParams.get('db');
if (db) {
var option = $('<option></option>');

View File

@ -853,10 +853,6 @@ export function onloadIdleEvent () {
if (! $('#modalOverlay').length) {
$('fieldset').not(':disabled').attr('disabled', 'disabled').addClass('disabled_for_expiration');
$('body').append(data.error);
$('.ui-dialog').each(function () {
$('#' + $(this).attr('aria-describedby')).dialog('close');
});
$('#input_username').trigger('focus');
} else {
Navigation.update(CommonParams.set('token', data.new_token));
@ -1776,11 +1772,6 @@ export function onloadCreateTableEvents (): void {
.html('');
ajaxShowMessage(data.message);
// Only if the create table dialog (distinct panel) exists
var $createTableDialog = $('#create_table_dialog');
if ($createTableDialog.length > 0) {
$createTableDialog.dialog('close').remove();
}
$('#tableslistcontainer').before(data.formatted_sql);
@ -2077,10 +2068,8 @@ export function onloadChangePasswordEvents (): void {
var $pageContent = $('#page_content');
$pageContent.prepend(data.message);
highlightSql($pageContent);
$('#change_password_dialog').hide().remove();
$('#edit_user_dialog').dialog('close').remove();
ajaxRemoveMessage($msgbox);
}); // end $.post()
});
$('#changePasswordModal').modal('hide');
};
@ -2116,15 +2105,7 @@ export function onloadChangePasswordEvents (): void {
$('#fieldset_change_password_footer').hide();
ajaxRemoveMessage($msgbox);
displayPasswordGenerateButton();
$('#change_password_form').on('submit', function (e) {
e.preventDefault();
$(this)
.closest('.ui-dialog')
.find('.ui-dialog-buttonpane .ui-button')
.first()
.trigger('click');
});
}); // end $.get()
});
});
}
@ -3311,24 +3292,6 @@ export function onloadCreateView () {
return false;
});
/**
* Attach Ajax event handlers for input fields in the editor
* and used to submit the Ajax request when the ENTER key is pressed.
*/
if ($('#createViewModal').length !== 0) {
$(document).on('keydown', '#createViewModal input, #createViewModal select', function (e) {
if (e.which === 13) { // 13 is the ENTER key
e.preventDefault();
// with preventing default, selection by <select> tag
// was also prevented in IE
$(this).trigger('blur');
$(this).closest('.ui-dialog').find('.ui-button').first().trigger('click');
}
}); // end $(document).on()
}
if ($('textarea[name="view[as]"]').length !== 0) {
window.codeMirrorEditor = getSqlEditor($('textarea[name="view[as]"]'));
}

View File

@ -238,8 +238,6 @@ export default function onloadNavigation () {
$(document).on('click', 'a.unhideNavItem.ajax', function (event) {
event.preventDefault();
var $tr = $(this).parents('tr');
var $hiddenTableCount = $tr.parents('tbody').children().length;
var $hideDialogBox = $tr.closest('div.ui-dialog');
var $msg = ajaxShowMessage();
var argSep = CommonParams.get('arg_separator');
var params = $(this).getPostData();
@ -252,10 +250,6 @@ export default function onloadNavigation () {
ajaxRemoveMessage($msg);
if (typeof data !== 'undefined' && data.success === true) {
$tr.remove();
if ($hiddenTableCount === 1) {
$hideDialogBox.remove();
}
Navigation.reload();
} else {
ajaxShowMessage(data.error);

View File

@ -24,34 +24,11 @@ var chartSize;
var monitorSettings;
function serverResponseError () {
var btns = {
[window.Messages.strReloadPage]: {
text: window.Messages.strReloadPage,
class: 'btn btn-primary',
click: function () {
window.location.reload();
},
},
};
$('#emptyDialog').dialog({
classes: {
'ui-dialog-titlebar-close': 'btn-close'
},
title: window.Messages.strRefreshFailed
});
window.bootstrap.Modal.getOrCreateInstance('#serverResponseErrorModal').show();
}
$('#emptyDialog').html(
getImageTag('s_attention') +
window.Messages.strInvalidResponseExplanation
);
$('#emptyDialog').dialog({
classes: {
'ui-dialog-titlebar-close': 'btn-close'
},
// @ts-ignore
buttons: btns
});
function serverResponseErrorModalReloadEventHandler () {
window.location.reload();
}
/**
@ -111,16 +88,17 @@ AJAX.registerOnload('server/status/monitor.js', function () {
});
AJAX.registerTeardown('server/status/monitor.js', function () {
const serverResponseErrorModalReloadButton = document.getElementById('serverResponseErrorModalReloadButton');
serverResponseErrorModalReloadButton?.removeEventListener('click', serverResponseErrorModalReloadEventHandler);
$('#monitorRearrangeChartButton').off('click');
$('#monitorDoneRearrangeChartButton').off('click');
$('#monitorChartColumnsSelect').off('change');
$('#monitorChartRefreshRateSelect').off('change');
$('#monitorAddNewChartButton').off('click');
$('#monitorExportConfigButton').off('click');
$('#monitorImportConfigButton').off('click');
$('#monitorResetConfigButton').off('click');
$('#monitorPauseResumeButton').off('click');
$('#monitorInstructionsButton').off('click');
$('input[name="chartType"]').off('click');
$('input[name="useDivisor"]').off('click');
$('input[name="useUnit"]').off('click');
@ -136,6 +114,9 @@ AJAX.registerTeardown('server/status/monitor.js', function () {
});
AJAX.registerOnload('server/status/monitor.js', function () {
const serverResponseErrorModalReloadButton = document.getElementById('serverResponseErrorModalReloadButton');
serverResponseErrorModalReloadButton?.addEventListener('click', serverResponseErrorModalReloadEventHandler);
$('#loadingMonitorIcon').remove();
// Codemirror is loaded on demand so we might need to initialize it
if (! window.codeMirrorEditor) {
@ -677,99 +658,71 @@ AJAX.registerOnload('server/status/monitor.js', function () {
}, 100);
});
$('#monitorImportConfigButton').on('click', function () {
$('#emptyDialog').dialog({
classes: {
'ui-dialog-titlebar-close': 'btn-close'
},
title: window.Messages.strImportDialogTitle
});
function monitorImportConfigImportEventHandler () {
var input = ($('#monitorImportConfigModal').find('#import_file') as JQuery<HTMLInputElement>)[0];
var reader = new FileReader();
$('#emptyDialog').html(window.Messages.strImportDialogMessage + '<br><form>' +
'<input type="file" name="file" id="import_file"> </form>');
var dlgBtns = {
[window.Messages.strImport]: {
text: window.Messages.strImport,
class: 'btn btn-primary',
},
[window.Messages.strCancel]: {
text: window.Messages.strCancel,
class: 'btn btn-secondary',
},
reader.onerror = function (event) {
alert(window.Messages.strFailedParsingConfig + '\n' + event.target.error.code);
};
// @ts-ignore
dlgBtns[window.Messages.strImport].click = function () {
var input = ($('#emptyDialog').find('#import_file') as JQuery<HTMLInputElement>)[0];
var reader = new FileReader();
reader.onload = function (e) {
var data = (e.target.result as string);
var json = null;
// Try loading config
try {
json = JSON.parse(data);
} catch (err) {
alert(window.Messages.strFailedParsingConfig);
window.bootstrap.Modal.getOrCreateInstance('#monitorImportConfigModal').hide();
reader.onerror = function (event) {
alert(window.Messages.strFailedParsingConfig + '\n' + event.target.error.code);
};
reader.onload = function (e) {
var data = (e.target.result as string);
var json = null;
// Try loading config
try {
json = JSON.parse(data);
} catch (err) {
alert(window.Messages.strFailedParsingConfig);
$('#emptyDialog').dialog('close');
return;
}
// Basic check, is this a monitor config json?
if (! json || ! json.monitorCharts || ! json.monitorCharts) {
alert(window.Messages.strFailedParsingConfig);
$('#emptyDialog').dialog('close');
return;
}
// If json ok, try applying config
try {
if (isStorageSupported('localStorage')) {
window.localStorage.monitorCharts = JSON.stringify(json.monitorCharts);
window.localStorage.monitorSettings = JSON.stringify(json.monitorSettings);
}
rebuildGrid();
} catch (err) {
alert(window.Messages.strFailedBuildingGrid);
// If an exception is thrown, load default again
if (isStorageSupported('localStorage')) {
window.localStorage.removeItem('monitorCharts');
window.localStorage.removeItem('monitorSettings');
}
rebuildGrid();
}
$('#emptyDialog').dialog('close');
};
if (input.files[0]) {
reader.readAsText(input.files[0]);
return;
}
// Basic check, is this a monitor config json?
if (! json || ! json.monitorCharts || ! json.monitorCharts) {
alert(window.Messages.strFailedParsingConfig);
window.bootstrap.Modal.getOrCreateInstance('#monitorImportConfigModal').hide();
return;
}
// If json ok, try applying config
try {
if (isStorageSupported('localStorage')) {
window.localStorage.monitorCharts = JSON.stringify(json.monitorCharts);
window.localStorage.monitorSettings = JSON.stringify(json.monitorSettings);
}
rebuildGrid();
} catch (err) {
alert(window.Messages.strFailedBuildingGrid);
// If an exception is thrown, load default again
if (isStorageSupported('localStorage')) {
window.localStorage.removeItem('monitorCharts');
window.localStorage.removeItem('monitorSettings');
}
rebuildGrid();
}
window.bootstrap.Modal.getOrCreateInstance('#monitorImportConfigModal').hide();
};
// @ts-ignore
dlgBtns[window.Messages.strCancel].click = function () {
$(this).dialog('close');
};
if (input.files[0]) {
reader.readAsText(input.files[0]);
}
}
$('#emptyDialog').dialog({
classes: {
'ui-dialog-titlebar-close': 'btn-close'
},
width: 'auto',
height: 'auto',
// @ts-ignore
buttons: dlgBtns
});
const monitorImportConfigModal = document.getElementById('monitorImportConfigModal');
monitorImportConfigModal.addEventListener('shown.bs.modal', function () {
const monitorImportConfigImportButton = document.getElementById('monitorImportConfigImportButton');
monitorImportConfigImportButton?.addEventListener('click', monitorImportConfigImportEventHandler);
});
monitorImportConfigModal.addEventListener('hidden.bs.modal', function () {
const monitorImportConfigImportButton = document.getElementById('monitorImportConfigImportButton');
monitorImportConfigImportButton?.removeEventListener('click', monitorImportConfigImportEventHandler);
});
$('#monitorResetConfigButton').on('click', function () {
@ -795,158 +748,141 @@ AJAX.registerOnload('server/status/monitor.js', function () {
}
});
$('#monitorInstructionsButton').on('click', function () {
var $dialog = $('#monitorInstructionsDialog');
var dlgBtns = {
[window.Messages.strClose]: {
text: window.Messages.strClose,
class: 'btn btn-primary',
click: function () {
$(this).dialog('close');
}
},
const $dialog = $('#monitorInstructionsModal');
function loadLogVars (getvars = undefined) {
var vars = {
'ajax_request': true,
'server': CommonParams.get('server'),
};
$dialog.dialog({
classes: {
'ui-dialog-titlebar-close': 'btn-close'
},
width: '60%',
height: 'auto',
// @ts-ignore
buttons: dlgBtns
}).find('img.ajaxIcon').show();
if (getvars) {
$.extend(vars, getvars);
}
var loadLogVars = function (getvars = undefined) {
var vars = {
'ajax_request': true,
'server': CommonParams.get('server')
};
if (getvars) {
$.extend(vars, getvars);
}
$.post('index.php?route=/server/status/monitor/log-vars', vars,
function (data) {
var logVars;
if (typeof data !== 'undefined' && data.success === true) {
logVars = data.message;
} else {
window.bootstrap.Modal.getOrCreateInstance('#monitorInstructionsModal').hide();
serverResponseError();
$.post('index.php?route=/server/status/monitor/log-vars', vars,
function (data) {
var logVars;
if (typeof data !== 'undefined' && data.success === true) {
logVars = data.message;
} else {
return serverResponseError();
}
return;
}
var icon = getImageTag('s_success');
var msg = '';
var str = '';
if (logVars.general_log === 'ON') {
if (logVars.slow_query_log === 'ON') {
msg = window.Messages.strBothLogOn;
} else {
msg = window.Messages.strGenLogOn;
}
}
if (msg.length === 0 && logVars.slow_query_log === 'ON') {
msg = window.Messages.strSlowLogOn;
}
if (msg.length === 0) {
icon = getImageTag('s_error');
msg = window.Messages.strBothLogOff;
}
str = '<b>' + window.Messages.strCurrentSettings + '</b><br><div class="smallIndent">';
str += icon + msg + '<br>';
if (logVars.log_output !== 'TABLE') {
str += getImageTag('s_error') + ' ' + window.Messages.strLogOutNotTable + '<br>';
} else {
str += getImageTag('s_success') + ' ' + window.Messages.strLogOutIsTable + '<br>';
}
var icon = getImageTag('s_success');
var msg = '';
var str = '';
if (logVars.general_log === 'ON') {
if (logVars.slow_query_log === 'ON') {
if (logVars.long_query_time > 2) {
str += getImageTag('s_attention') + ' ';
str += window.sprintf(window.Messages.strSmallerLongQueryTimeAdvice, logVars.long_query_time);
str += '<br>';
}
msg = window.Messages.strBothLogOn;
} else {
msg = window.Messages.strGenLogOn;
}
}
if (logVars.long_query_time < 2) {
str += getImageTag('s_success') + ' ';
str += window.sprintf(window.Messages.strLongQueryTimeSet, logVars.long_query_time);
str += '<br>';
}
if (msg.length === 0 && logVars.slow_query_log === 'ON') {
msg = window.Messages.strSlowLogOn;
}
if (msg.length === 0) {
icon = getImageTag('s_error');
msg = window.Messages.strBothLogOff;
}
str = '<b>' + window.Messages.strCurrentSettings + '</b><br><div class="smallIndent">';
str += icon + msg + '<br>';
if (logVars.log_output !== 'TABLE') {
str += getImageTag('s_error') + ' ' + window.Messages.strLogOutNotTable + '<br>';
} else {
str += getImageTag('s_success') + ' ' + window.Messages.strLogOutIsTable + '<br>';
}
if (logVars.slow_query_log === 'ON') {
if (logVars.long_query_time > 2) {
str += getImageTag('s_attention') + ' ';
str += window.sprintf(window.Messages.strSmallerLongQueryTimeAdvice, logVars.long_query_time);
str += '<br>';
}
str += '</div>';
if (logVars.long_query_time < 2) {
str += getImageTag('s_success') + ' ';
str += window.sprintf(window.Messages.strLongQueryTimeSet, logVars.long_query_time);
str += '<br>';
}
}
if (isSuperUser) {
str += '<p></p><b>' + window.Messages.strChangeSettings + '</b>';
str += '<div class="smallIndent">';
str += window.Messages.strSettingsAppliedGlobal + '<br>';
str += '</div>';
var varValue: string | number = 'TABLE';
if (logVars.log_output === 'TABLE') {
varValue = 'FILE';
}
if (isSuperUser) {
str += '<p></p><b>' + window.Messages.strChangeSettings + '</b>';
str += '<div class="smallIndent">';
str += window.Messages.strSettingsAppliedGlobal + '<br>';
str += '- <a class="set" href="#log_output-' + varValue + '">';
str += window.sprintf(window.Messages.strSetLogOutput, varValue);
str += ' </a><br>';
var varValue: string | number = 'TABLE';
if (logVars.log_output === 'TABLE') {
varValue = 'FILE';
}
if (logVars.general_log !== 'ON') {
str += '- <a class="set" href="#general_log-ON">';
str += window.sprintf(window.Messages.strEnableVar, 'general_log');
str += ' </a><br>';
} else {
str += '- <a class="set" href="#general_log-OFF">';
str += window.sprintf(window.Messages.strDisableVar, 'general_log');
str += ' </a><br>';
}
str += '- <a class="set" href="#log_output-' + varValue + '">';
str += window.sprintf(window.Messages.strSetLogOutput, varValue);
str += ' </a><br>';
if (logVars.slow_query_log !== 'ON') {
str += '- <a class="set" href="#slow_query_log-ON">';
str += window.sprintf(window.Messages.strEnableVar, 'slow_query_log');
str += ' </a><br>';
} else {
str += '- <a class="set" href="#slow_query_log-OFF">';
str += window.sprintf(window.Messages.strDisableVar, 'slow_query_log');
str += ' </a><br>';
}
varValue = 5;
if (logVars.long_query_time > 2) {
varValue = 1;
}
str += '- <a class="set" href="#long_query_time-' + varValue + '">';
str += window.sprintf(window.Messages.setSetLongQueryTime, varValue);
if (logVars.general_log !== 'ON') {
str += '- <a class="set" href="#general_log-ON">';
str += window.sprintf(window.Messages.strEnableVar, 'general_log');
str += ' </a><br>';
} else {
str += window.Messages.strNoSuperUser + '<br>';
str += '- <a class="set" href="#general_log-OFF">';
str += window.sprintf(window.Messages.strDisableVar, 'general_log');
str += ' </a><br>';
}
str += '</div>';
if (logVars.slow_query_log !== 'ON') {
str += '- <a class="set" href="#slow_query_log-ON">';
str += window.sprintf(window.Messages.strEnableVar, 'slow_query_log');
str += ' </a><br>';
} else {
str += '- <a class="set" href="#slow_query_log-OFF">';
str += window.sprintf(window.Messages.strDisableVar, 'slow_query_log');
str += ' </a><br>';
}
$dialog.find('div.monitorUse').toggle(
logVars.log_output === 'TABLE' && (logVars.slow_query_log === 'ON' || logVars.general_log === 'ON')
);
varValue = 5;
if (logVars.long_query_time > 2) {
varValue = 1;
}
$dialog.find('div.ajaxContent').html(str);
$dialog.find('img.ajaxIcon').hide();
$dialog.find('a.set').on('click', function () {
var nameValue = $(this).attr('href').split('-');
loadLogVars({ varName: nameValue[0].substring(1), varValue: nameValue[1] });
$dialog.find('img.ajaxIcon').show();
});
str += '- <a class="set" href="#long_query_time-' + varValue + '">';
str += window.sprintf(window.Messages.setSetLongQueryTime, varValue);
str += ' </a><br>';
} else {
str += window.Messages.strNoSuperUser + '<br>';
}
);
};
str += '</div>';
$dialog.find('div.monitorUse').toggle(
logVars.log_output === 'TABLE' && (logVars.slow_query_log === 'ON' || logVars.general_log === 'ON'),
);
$dialog.find('div.ajaxContent').html(str);
$dialog.find('img.ajaxIcon').hide();
$dialog.find('a.set').on('click', function () {
var nameValue = $(this).attr('href').split('-');
loadLogVars({ varName: nameValue[0].substring(1), varValue: nameValue[1] });
$dialog.find('img.ajaxIcon').show();
});
},
);
}
const monitorInstructionsModal = document.getElementById('monitorInstructionsModal');
monitorInstructionsModal.addEventListener('shown.bs.modal', function () {
loadLogVars();
return false;
});
($('input[name="chartType"]') as JQuery<HTMLInputElement>).on('change', function () {
@ -1083,33 +1019,7 @@ AJAX.registerOnload('server/status/monitor.js', function () {
&& typeof window.localStorage.monitorVersion !== 'undefined'
&& monitorProtocolVersion !== window.localStorage.monitorVersion
) {
$('#emptyDialog').dialog({
classes: {
'ui-dialog-titlebar-close': 'btn-close'
},
title: window.Messages.strIncompatibleMonitorConfig
});
$('#emptyDialog').html(window.Messages.strIncompatibleMonitorConfigDescription);
var dlgBtns = {
[window.Messages.strClose]: {
text: window.Messages.strClose,
class: 'btn btn-primary',
click: function () {
$(this).dialog('close');
}
},
};
$('#emptyDialog').dialog({
classes: {
'ui-dialog-titlebar-close': 'btn-close'
},
width: 400,
// @ts-ignore
buttons: dlgBtns
});
window.bootstrap.Modal.getOrCreateInstance('#incompatibleMonitorConfigModal').show();
}
}
@ -1439,61 +1349,58 @@ AJAX.registerOnload('server/status/monitor.js', function () {
}
function getLogAnalyseDialog (min: Date, max: Date) {
var $logAnalyseDialog = $('#logAnalyseDialog');
var $dateStart = $logAnalyseDialog.find('input[name="dateStart"]');
var $dateEnd = $logAnalyseDialog.find('input[name="dateEnd"]');
$dateStart.prop('readonly', true);
$dateEnd.prop('readonly', true);
const logAnalyseModal = document.getElementById('logAnalyseModal');
var dlgBtns = {
[window.Messages.strFromSlowLog]: {
text: window.Messages.strFromSlowLog,
class: 'btn btn-secondary',
},
[window.Messages.strFromGeneralLog]: {
text: window.Messages.strFromGeneralLog,
class: 'btn btn-secondary',
},
};
// @ts-ignore
dlgBtns[window.Messages.strFromSlowLog].click = function () {
function logAnalyseModalSlowLogEventHandler () {
window.bootstrap.Modal.getOrCreateInstance(logAnalyseModal).hide();
loadLog('slow', min, max);
$(this).dialog('close');
};
}
// @ts-ignore
dlgBtns[window.Messages.strFromGeneralLog].click = function () {
function logAnalyseModalGeneralLogEventHandler () {
window.bootstrap.Modal.getOrCreateInstance(logAnalyseModal).hide();
loadLog('general', min, max);
$(this).dialog('close');
};
}
$logAnalyseDialog.dialog({
classes: {
'ui-dialog-titlebar-close': 'btn-close'
},
width: 'auto',
height: 'auto',
// @ts-ignore
buttons: dlgBtns
logAnalyseModal.addEventListener('shown.bs.modal', function () {
const logAnalyseModalSlowLogButton = document.getElementById('logAnalyseModalSlowLogButton');
logAnalyseModalSlowLogButton?.addEventListener('click', logAnalyseModalSlowLogEventHandler);
const logAnalyseModalGeneralLogButton = document.getElementById('logAnalyseModalGeneralLogButton');
logAnalyseModalGeneralLogButton?.addEventListener('click', logAnalyseModalGeneralLogEventHandler);
const $logAnalyseDialog = $('#logAnalyseDialog');
const $dateStart = $logAnalyseDialog.find('input[name="dateStart"]');
const $dateEnd = $logAnalyseDialog.find('input[name="dateEnd"]');
$dateStart.prop('readonly', true);
$dateEnd.prop('readonly', true);
addDatepicker($dateStart, 'datetime', {
showMillisec: false,
showMicrosec: false,
timeFormat: 'HH:mm:ss',
firstDay: window.firstDayOfCalendar
});
addDatepicker($dateEnd, 'datetime', {
showMillisec: false,
showMicrosec: false,
timeFormat: 'HH:mm:ss',
firstDay: window.firstDayOfCalendar
});
$dateStart.datepicker('setDate', min);
$dateEnd.datepicker('setDate', max);
});
addDatepicker($dateStart, 'datetime', {
showMillisec: false,
showMicrosec: false,
timeFormat: 'HH:mm:ss',
firstDay: window.firstDayOfCalendar
logAnalyseModal.addEventListener('hidden.bs.modal', function () {
const logAnalyseModalSlowLogButton = document.getElementById('logAnalyseModalSlowLogButton');
logAnalyseModalSlowLogButton?.removeEventListener('click', logAnalyseModalSlowLogEventHandler);
const logAnalyseModalGeneralLogButton = document.getElementById('logAnalyseModalGeneralLogButton');
logAnalyseModalGeneralLogButton?.removeEventListener('click', logAnalyseModalGeneralLogEventHandler);
});
addDatepicker($dateEnd, 'datetime', {
showMillisec: false,
showMicrosec: false,
timeFormat: 'HH:mm:ss',
firstDay: window.firstDayOfCalendar
});
$dateStart.datepicker('setDate', min);
$dateEnd.datepicker('setDate', max);
window.bootstrap.Modal.getOrCreateInstance(logAnalyseModal).show();
}
function loadLog (type: string, min: Date, max: Date) {
@ -1521,7 +1428,9 @@ AJAX.registerOnload('server/status/monitor.js', function () {
if (typeof data !== 'undefined' && data.success === true) {
chartData = data.message;
} else {
return serverResponseError();
serverResponseError();
return;
}
var value;
@ -1747,43 +1656,16 @@ AJAX.registerOnload('server/status/monitor.js', function () {
opts.limitTypes = false;
}
$('#emptyDialog').dialog({
classes: {
'ui-dialog-titlebar-close': 'btn-close'
},
title: window.Messages.strAnalysingLogsTitle
});
const analysingLogsModal = document.getElementById('analysingLogsModal');
$('#emptyDialog').html(window.Messages.strAnalysingLogs +
' <img class="ajaxIcon" src="' + window.themeImagePath +
'ajax_clock_small.gif" alt="">');
var dlgBtns = {
[window.Messages.strCancelRequest]: {
text: window.Messages.strCancelRequest,
class: 'btn btn-primary',
},
};
// @ts-ignore
dlgBtns[window.Messages.strCancelRequest].click = function () {
analysingLogsModal.addEventListener('hidden.bs.modal', function () {
if (logRequest !== null) {
logRequest.abort();
}
$(this).dialog('close');
};
$('#emptyDialog').dialog({
classes: {
'ui-dialog-titlebar-close': 'btn-close'
},
width: 'auto',
height: 'auto',
// @ts-ignore
buttons: dlgBtns
});
window.bootstrap.Modal.getOrCreateInstance(analysingLogsModal).show();
var url = 'index.php?route=/server/status/monitor/slow-log';
if (opts.src === 'general') {
url = 'index.php?route=/server/status/monitor/general-log';
@ -1801,56 +1683,32 @@ AJAX.registerOnload('server/status/monitor.js', function () {
},
function (data) {
var logData;
var dlgBtns = {
[window.Messages.strClose]: {
text: window.Messages.strClose,
class: 'btn btn-primary',
},
};
if (typeof data !== 'undefined' && data.success === true) {
logData = data.message;
} else {
return serverResponseError();
window.bootstrap.Modal.getOrCreateInstance(analysingLogsModal).hide();
serverResponseError();
return;
}
if (logData.rows.length === 0) {
$('#emptyDialog').dialog({
classes: {
'ui-dialog-titlebar-close': 'btn-close'
},
title: window.Messages.strNoDataFoundTitle,
});
$('#emptyDialog').html('<p>' + window.Messages.strNoDataFound + '</p>');
// @ts-ignore
dlgBtns[window.Messages.strClose].click = function () {
$(this).dialog('close');
};
$('#emptyDialog').dialog('option', 'buttons', dlgBtns);
window.bootstrap.Modal.getOrCreateInstance(analysingLogsModal).hide();
window.bootstrap.Modal.getOrCreateInstance('#analysingLogsNoDataFoundModal').show();
return;
}
runtime.logDataCols = buildLogTable(logData, opts.removeVariables);
/* Show some stats in the dialog */
$('#emptyDialog').dialog({
classes: {
'ui-dialog-titlebar-close': 'btn-close'
},
title: window.Messages.strLoadingLogs
});
$('#emptyDialog').html('<p>' + window.Messages.strLogDataLoaded + '</p>');
const analysingLogsLogDataLoadedModalBody = $('#analysingLogsLogDataLoadedModal .modal-body');
$.each(logData.sum, function (key: string, value) {
var newKey = key.charAt(0).toUpperCase() + key.slice(1).toLowerCase();
if (newKey === 'Total') {
newKey = '<b>' + newKey + '</b>';
}
$('#emptyDialog').append(newKey + ': ' + value + '<br>');
analysingLogsLogDataLoadedModalBody.append(newKey + ': ' + value + '<br>');
});
/* Add filter options if more than a bunch of rows there to filter */
@ -1882,17 +1740,25 @@ AJAX.registerOnload('server/status/monitor.js', function () {
}
}
dlgBtns[window.Messages.strJumpToTable] = {
text: window.Messages.strJumpToTable,
class: 'btn btn-secondary',
// @ts-ignore
click: function () {
$(this).dialog('close');
$(document).scrollTop($('#logTable').offset().top);
},
};
const analysingLogsLogDataLoadedModal = document.getElementById('analysingLogsLogDataLoadedModal');
$('#emptyDialog').dialog('option', 'buttons', dlgBtns);
function analysingLogsLogDataLoadedModalJumpEventHandler () {
window.bootstrap.Modal.getOrCreateInstance(analysingLogsLogDataLoadedModal).hide();
$(document).scrollTop($('#logTable').offset().top);
}
analysingLogsLogDataLoadedModal.addEventListener('shown.bs.modal', function () {
const analysingLogsLogDataLoadedModalJumpButton = document.getElementById('analysingLogsLogDataLoadedModalJumpButton');
analysingLogsLogDataLoadedModalJumpButton?.addEventListener('click', analysingLogsLogDataLoadedModalJumpEventHandler);
});
analysingLogsLogDataLoadedModal.addEventListener('hidden.bs.modal', function () {
const analysingLogsLogDataLoadedModalJumpButton = document.getElementById('analysingLogsLogDataLoadedModalJumpButton');
analysingLogsLogDataLoadedModalJumpButton?.removeEventListener('click', analysingLogsLogDataLoadedModalJumpEventHandler);
});
window.bootstrap.Modal.getOrCreateInstance(analysingLogsModal).hide();
window.bootstrap.Modal.getOrCreateInstance(analysingLogsLogDataLoadedModal).show();
}
);
@ -2166,64 +2032,48 @@ AJAX.registerOnload('server/status/monitor.js', function () {
/* Opens the query analyzer dialog */
function openQueryAnalyzer () {
var rowData = $(this).parent().data('query');
var query = rowData.argument || rowData.sql_text;
const rowData = $(this).parent().data('query');
let profilingChart = null;
if (window.codeMirrorEditor) {
window.codeMirrorEditor.setValue(query);
// Codemirror is bugged, it doesn't refresh properly sometimes.
// Following lines seem to fix that
setTimeout(function () {
window.codeMirrorEditor.refresh();
}, 50);
} else {
$('#sqlquery').val(query);
function queryAnalyzerModalSaveEventHandler () {
profilingChart = loadQueryAnalysis(rowData);
}
var profilingChart = null;
var dlgBtns = {
[window.Messages.strAnalyzeQuery]: {
text: window.Messages.strAnalyzeQuery,
class: 'btn btn-primary',
},
[window.Messages.strClose]: {
text: window.Messages.strClose,
class: 'btn btn-secondary',
},
};
const queryAnalyzerModal = document.getElementById('queryAnalyzerModal');
queryAnalyzerModal.addEventListener('shown.bs.modal', function () {
const queryAnalyzerModalAnalyseButton = document.getElementById('queryAnalyzerModalAnalyseButton');
queryAnalyzerModalAnalyseButton?.addEventListener('click', queryAnalyzerModalSaveEventHandler);
// @ts-ignore
dlgBtns[window.Messages.strAnalyzeQuery].click = function () {
profilingChart = loadQueryAnalysis(rowData);
};
// @ts-ignore
dlgBtns[window.Messages.strClose].click = function () {
$(this).dialog('close');
};
$('#queryAnalyzerDialog').dialog({
classes: {
'ui-dialog-titlebar-close': 'btn-close'
},
width: 'auto',
height: 'auto',
resizable: true,
// @ts-ignore
buttons: dlgBtns,
close: function () {
if (profilingChart !== null) {
profilingChart.destroy();
}
$('#queryAnalyzerDialog').find('div.placeHolder').html('');
if (window.codeMirrorEditor) {
window.codeMirrorEditor.setValue('');
} else {
$('#sqlquery').val('');
}
const query = rowData.argument || rowData.sql_text;
if (window.codeMirrorEditor) {
window.codeMirrorEditor.setValue(query);
// Codemirror is bugged, it doesn't refresh properly sometimes.
// Following lines seem to fix that
setTimeout(function () {
window.codeMirrorEditor.refresh();
}, 50);
} else {
$('#sqlquery').val(query);
}
});
queryAnalyzerModal.addEventListener('hidden.bs.modal', function () {
const queryAnalyzerModalAnalyseButton = document.getElementById('queryAnalyzerModalAnalyseButton');
queryAnalyzerModalAnalyseButton?.removeEventListener('click', queryAnalyzerModalSaveEventHandler);
if (profilingChart !== null) {
profilingChart.destroy();
}
queryAnalyzerModal.querySelector('div.placeHolder').textContent = '';
if (window.codeMirrorEditor) {
window.codeMirrorEditor.setValue('');
} else {
$('#sqlquery').val('');
}
});
window.bootstrap.Modal.getOrCreateInstance(queryAnalyzerModal).show();
}
/* Loads and displays the analyzed query data */

View File

@ -298,11 +298,6 @@ AJAX.registerOnload('table/structure.js', function () {
$(document).on('click', '#move_columns_anchor', function (e) {
e.preventDefault();
var buttonOptionsError = {};
buttonOptionsError[window.Messages.strOK] = function () {
$(this).dialog('close').remove();
};
var columns = [];
$('#tablestructure').find('tbody tr').each(function () {

View File

@ -14,11 +14,6 @@ AJAX.registerTeardown('triggers.js', function () {
});
const DatabaseTriggers = {
/**
* @var $ajaxDialog Query object containing the reference to the
* dialog that contains the editor
*/
$ajaxDialog: null,
/**
* @var syntaxHiglighter Reference to the codemirror editor
*/
@ -121,43 +116,23 @@ const DatabaseTriggers = {
}
ajaxRemoveMessage($msg);
/**
* @var buttonOptions Object containing options
* for jQueryUI dialog buttons
*/
var buttonOptions = {
[window.Messages.strClose]: {
text: window.Messages.strClose,
class: 'btn btn-primary',
},
};
// @ts-ignore
buttonOptions[window.Messages.strClose].click = function () {
$(this).dialog('close').remove();
};
/**
* Display the dialog to the user
*/
data.message = '<textarea cols="40" rows="15" class="w-100">' + data.message + '</textarea>';
var $ajaxDialog = $('<div>' + data.message + '</div>').dialog({
classes: {
'ui-dialog-titlebar-close': 'btn-close'
},
width: 500,
// @ts-ignore
buttons: buttonOptions,
title: data.title
const triggersExportTextarea = '<textarea id="triggersExportTextarea" cols="40" rows="15" class="form-control" aria-label="' + window.Messages.strTrigger + '"></textarea>';
const triggersExportModal = document.getElementById('triggersExportModal');
triggersExportModal.addEventListener('shown.bs.modal', function () {
triggersExportModal.querySelector('.modal-title').textContent = data.title;
triggersExportModal.querySelector('.modal-body').innerHTML = triggersExportTextarea;
document.getElementById('triggersExportTextarea').textContent = data.message;
getSqlEditor($('#triggersExportTextarea'));
});
// Attach syntax highlighted editor to export dialog
/**
* @var $elm jQuery object containing the reference
* to the Export textarea.
*/
var $elm = $ajaxDialog.find('textarea');
getSqlEditor($elm);
} // end showExport()
}, // end exportDialog()
triggersExportModal.addEventListener('hidden.bs.modal', function () {
triggersExportModal.querySelector('.modal-body').innerHTML = triggersExportTextarea;
});
window.bootstrap.Modal.getOrCreateInstance(triggersExportModal).show();
}
},
editorDialog: function (isNew, $this) {
var that = this;
/**
@ -185,22 +160,12 @@ const DatabaseTriggers = {
return;
}
var buttonOptions = {
[window.Messages.strGo]: {
text: window.Messages.strGo,
class: 'btn btn-primary',
},
[window.Messages.strClose]: {
text: window.Messages.strClose,
class: 'btn btn-secondary',
},
};
// We have successfully fetched the editor form
ajaxRemoveMessage($msg);
// Now define the function that is called when
// the user presses the "Go" button
// @ts-ignore
buttonOptions[window.Messages.strGo].click = function () {
let isEditMode = false;
function triggersEditorModalSaveEventHandler () {
// Move the data from the codemirror editor back to the
// textarea, where it can be used in the form submission.
if (typeof window.CodeMirror !== 'undefined') {
@ -231,10 +196,10 @@ const DatabaseTriggers = {
// Item created successfully
ajaxRemoveMessage($msg);
slidingMessage(data.message);
that.$ajaxDialog.dialog('close');
window.bootstrap.Modal.getOrCreateInstance('#triggersEditorModal').hide();
// If we are in 'edit' mode, we must
// remove the reference to the old row.
if (mode === 'edit' && $editRow !== null) {
if (isEditMode && $editRow !== null) {
$editRow.remove();
}
@ -328,72 +293,59 @@ const DatabaseTriggers = {
Navigation.reload();
}); // end $.post()
}; // end of function that handles the submission of the Editor
// @ts-ignore
buttonOptions[window.Messages.strClose].click = function () {
$(this).dialog('close');
};
/**
* Display the dialog to the user
*/
that.$ajaxDialog = $('<div id="rteDialog">' + data.message + '</div>').dialog({
classes: {
'ui-dialog-titlebar-close': 'btn-close'
},
width: '70%',
minWidth: 500,
// @ts-ignore
buttons: buttonOptions,
// Issue #15810 - use button titles for modals (eg: new procedure)
// Respect the order: title on href tag, href content, title sent in response
title: $this.attr('title') || $this.text() || $(data.title).text(),
modal: true,
open: function () {
$('#rteDialog').dialog('option', 'max-height', $(window).height());
if ($('#rteDialog').parents('.ui-dialog').height() > $(window).height()) {
$('#rteDialog').dialog('option', 'height', $(window).height());
}
$(this).find('input[name=item_name]').trigger('focus');
$(this).find('input.datefield').each(function () {
addDatepicker($(this).css('width', '95%'), 'date');
});
$(this).find('input.datetimefield').each(function () {
addDatepicker($(this).css('width', '95%'), 'datetime');
});
// @ts-ignore
$.datepicker.initialized = false;
},
close: function () {
$(this).remove();
}
});
/**
* @var mode Used to remember whether the editor is in
* "Edit" or "Add" mode
*/
var mode = 'add';
if ($('input[name=editor_process_edit]').length > 0) {
mode = 'edit';
}
// Attach syntax highlighted editor to the definition
/**
* @var elm jQuery object containing the reference to
* the Definition textarea.
*/
var $elm = $('textarea[name=item_definition]').last();
var linterOptions = {
editorType: 'trigger',
};
that.syntaxHiglighter = getSqlEditor($elm, {}, 'vertical', linterOptions);
window.codeMirrorEditor = that.syntaxHiglighter;
}); // end $.get()
const triggersEditorModal = document.getElementById('triggersEditorModal');
triggersEditorModal.addEventListener('shown.bs.modal', function () {
/**
* Issue #15810 - use button titles for modals (eg: new procedure)
* Respect the order: title on href tag, href content, title sent in response
*/
triggersEditorModal.querySelector('.modal-title').textContent = $this.attr('title') || $this.text() || $(data.title).text();
triggersEditorModal.querySelector('.modal-body').innerHTML = data.message;
const triggersEditorModalSaveButton = document.getElementById('triggersEditorModalSaveButton');
triggersEditorModalSaveButton?.addEventListener('click', triggersEditorModalSaveEventHandler);
$(this).find('input[name=item_name]').trigger('focus');
$(this).find('input.datefield').each(function () {
addDatepicker($(this).css('width', '95%'), 'date');
});
$(this).find('input.datetimefield').each(function () {
addDatepicker($(this).css('width', '95%'), 'datetime');
});
// @ts-ignore
$.datepicker.initialized = false;
if ($('input[name=editor_process_edit]').length > 0) {
isEditMode = true;
}
// Attach syntax highlighted editor to the definition
/**
* @var elm jQuery object containing the reference to
* the Definition textarea.
*/
var $elm = $('textarea[name=item_definition]').last();
var linterOptions = {
editorType: 'trigger',
};
that.syntaxHiglighter = getSqlEditor($elm, {}, 'vertical', linterOptions);
window.codeMirrorEditor = that.syntaxHiglighter;
});
triggersEditorModal.addEventListener('hidden.bs.modal', function () {
const triggersEditorModalSaveButton = document.getElementById('triggersEditorModalSaveButton');
triggersEditorModalSaveButton?.removeEventListener('click', triggersEditorModalSaveEventHandler);
document.getElementById('triggersEditorModal').querySelector('.modal-body').innerHTML = '<div class="spinner-border" role="status">' +
'<span class="visually-hidden">' + window.Messages.strLoading + '</span></div>';
});
window.bootstrap.Modal.getOrCreateInstance(triggersEditorModal).show();
});
},
dropDialog: function ($this) {

View File

@ -153,4 +153,39 @@
</div>
</div>
</div>
<div class="modal fade" id="eventsEditorModal" tabindex="-1" aria-labelledby="eventsEditorModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="eventsEditorModalLabel">{{ t('Event editor') }}</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{{ t('Close') }}"></button>
</div>
<div class="modal-body">
<div class="spinner-border" role="status">
<span class="visually-hidden">{{ t('Loading…') }}</span>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ t('Close') }}</button>
<button type="button" class="btn btn-primary" id="eventsEditorModalSaveButton">{{ t('Save changes') }}</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="eventsExportModal" tabindex="-1" aria-labelledby="eventsExportModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="eventsExportModalLabel">{{ t('Export event') }}</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{{ t('Close') }}"></button>
</div>
<div class="modal-body"></div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ t('Close') }}</button>
</div>
</div>
</div>
</div>
</div>

View File

@ -6,7 +6,7 @@
<div class="mb-3 d-print-none">
<button type="button" class="btn btn-primary" id="monitorPauseResumeButton">{{ get_icon('play', t('Start monitor')) }}</button>
<button type="button" class="btn btn-secondary" data-bs-toggle="collapse" data-bs-target="#monitorSettingsContent" aria-expanded="false" aria-controls="monitorSettingsContent">{{ get_icon('s_cog', t('Settings')) }}</button>
<button type="button" class="btn btn-secondary" id="monitorInstructionsButton">{{ get_icon('b_help', t('Instructions/Setup')) }}</button>
<button type="button" class="btn btn-secondary" data-bs-toggle="modal" data-bs-target="#monitorInstructionsModal">{{ get_icon('b_help', t('Instructions/Setup')) }}</button>
</div>
<div class="collapse" id="monitorSettingsContent">
@ -50,7 +50,28 @@
<span class="text-body-secondary">{{ t('The arrangement of the charts is stored to the browsers local storage. You may want to export it if you have a complicated set up.') }}</span>
</p>
<div>
<button type="button" class="btn btn-secondary" id="monitorImportConfigButton">{{ t('Import') }}</button>
<button type="button" class="btn btn-secondary" data-bs-toggle="modal" data-bs-target="#monitorImportConfigModal">{{ t('Import') }}</button>
<div class="modal fade" id="monitorImportConfigModal" tabindex="-1" aria-labelledby="monitorImportConfigModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="monitorImportConfigModalLabel">{{ t('Importing system monitor configuration') }}</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{{ t('Close') }}"></button>
</div>
<div class="modal-body">
<form>
<label for="import_file" class="form-label">{{ t('Please select the file you want to import:') }}</label>
<input class="form-control" type="file" name="file" id="import_file">
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ t('Close') }}</button>
<button type="button" class="btn btn-primary" id="monitorImportConfigImportButton">{{ t('Import') }}</button>
</div>
</div>
</div>
</div>
<button type="button" class="btn btn-secondary" id="monitorExportConfigButton">{{ t('Export') }}</button>
<button type="button" class="btn btn-secondary" id="monitorResetConfigButton">{{ t('Reset to default') }}</button>
</div>
@ -59,32 +80,41 @@
</div>
</div>
<div id="monitorInstructionsDialog" title="{{ t('Monitor Instructions') }}" class="hide">
<p>
{{ t("The phpMyAdmin Monitor can assist you in optimizing the server configuration and track down time intensive queries. For the latter you will need to set log_output to 'TABLE' and have either the slow_query_log or general_log enabled. Note however, that the general_log produces a lot of data and increases server load by up to 15%.") }}
</p>
<img class="ajaxIcon" src="{{ image('ajax_clock_small.gif') }}" alt="{{ t('Loading…') }}">
<div class="modal fade" id="monitorInstructionsModal" tabindex="-1" aria-labelledby="monitorInstructionsModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="monitorInstructionsModalLabel">{{ t('System monitor instructions') }}</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{{ t('Close') }}"></button>
</div>
<div class="modal-body">
<p>
{{ t("The phpMyAdmin Monitor can assist you in optimizing the server configuration and track down time intensive queries. For the latter you will need to set log_output to 'TABLE' and have either the slow_query_log or general_log enabled. Note however, that the general_log produces a lot of data and increases server load by up to 15%.") }}
</p>
<img class="ajaxIcon" src="{{ image('ajax_clock_small.gif') }}" alt="{{ t('Loading…') }}">
<div class="ajaxContent"></div>
<br>
<div class="ajaxContent"></div>
<div class="monitorUse hide">
<p><strong>{{ t('Using the monitor:') }}</strong></p>
<p>
{{ t("Your browser will refresh all displayed charts in a regular interval. You may add charts and change the refresh rate under 'Settings', or remove any chart using the cog icon on each respective chart.") }}
</p>
<p>
{{ t('To display queries from the logs, click on any chart. Once confirmed, this will load a table of grouped queries, there you may click on any occurring SELECT statements to further analyze them.') }}
</p>
<p>
{{ get_image('s_attention') }}
<strong>{{ t('Please note:') }}</strong>
</p>
<p>
{{ t('Enabling the general_log may increase the server load by 5-15%. Also be aware that generating statistics from the logs is a load intensive task, so it is advisable to select only a small time span and to disable the general_log and empty its table once monitoring is not required any more.') }}
</p>
<div class="monitorUse hide">
<p><strong>{{ t('Using the monitor:') }}</strong></p>
<p>
{{ t("Your browser will refresh all displayed charts in a regular interval. You may add charts and change the refresh rate under 'Settings', or remove any chart using the cog icon on each respective chart.") }}
</p>
<p>
{{ t('To display queries from the logs, click on any chart. Once confirmed, this will load a table of grouped queries, there you may click on any occurring SELECT statements to further analyze them.') }}
</p>
<p>
{{ get_image('s_attention') }}
<strong>{{ t('Please note:') }}</strong>
</p>
<p>
{{ t('Enabling the general_log may increase the server load by 5-15%. Also be aware that generating statistics from the logs is a load intensive task, so it is advisable to select only a small time span and to disable the general_log and empty its table once monitoring is not required any more.') }}
</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal fade" id="addChartModal" tabindex="-1" aria-labelledby="addChartModalLabel" aria-hidden="true">
<div class="modal-dialog">
@ -186,37 +216,164 @@
</div>
</div>
<div id="logAnalyseDialog" title="{{ t('Log statistics') }}" class="hide">
<p>
{{ t('Selected time range:') }}
<input type="text" name="dateStart" class="datetimefield" value="">
-
<input type="text" name="dateEnd" class="datetimefield" value="">
</p>
<div class="modal fade" id="logAnalyseModal" tabindex="-1" aria-labelledby="logAnalyseModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="logAnalyseModalLabel">{{ t('Log statistics') }}</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{{ t('Close') }}"></button>
</div>
<div class="modal-body">
<div id="logAnalyseDialog">
<p>
{{ t('Selected time range:') }}
<input type="text" name="dateStart" class="datetimefield" value="">
-
<input type="text" name="dateEnd" class="datetimefield" value="">
</p>
<input type="checkbox" id="limitTypes" value="1" checked>
<label for="limitTypes">
{{ t('Only retrieve SELECT,INSERT,UPDATE and DELETE Statements') }}
</label>
<br>
<input type="checkbox" id="limitTypes" value="1" checked>
<label for="limitTypes">
{{ t('Only retrieve SELECT,INSERT,UPDATE and DELETE Statements') }}
</label>
<br>
<input type="checkbox" id="removeVariables" value="1" checked>
<label for="removeVariables">
{{ t('Remove variable data in INSERT statements for better grouping') }}
</label>
<input type="checkbox" id="removeVariables" value="1" checked>
<label for="removeVariables">
{{ t('Remove variable data in INSERT statements for better grouping') }}
</label>
<p>
{{ t('Choose from which log you want the statistics to be generated from.') }}
</p>
<p>
{{ t('Results are grouped by query text.') }}
</p>
<p>
{{ t('Choose from which log you want the statistics to be generated from.') }}
</p>
<p>
{{ t('Results are grouped by query text.') }}
</p>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ t('Close') }}</button>
<button type="button" class="btn btn-primary" id="logAnalyseModalSlowLogButton">{{ t('From slow log') }}</button>
<button type="button" class="btn btn-primary" id="logAnalyseModalGeneralLogButton">{{ t('From general log') }}</button>
</div>
</div>
</div>
</div>
<div id="queryAnalyzerDialog" title="{{ t('Query analyzer') }}" class="overflow-y-scroll hide">
<textarea id="sqlquery"></textarea>
<br>
<div class="placeHolder"></div>
<div class="modal fade" id="queryAnalyzerModal" tabindex="-1" aria-labelledby="queryAnalyzerModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="queryAnalyzerModalLabel">{{ t('Query analyzer') }}</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{{ t('Close') }}"></button>
</div>
<div class="modal-body">
<div id="queryAnalyzerDialog">
<div>
<textarea id="sqlquery" aria-label="{{ t('Query') }}"></textarea>
</div>
<div class="placeHolder"></div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ t('Close') }}</button>
<button type="button" class="btn btn-primary" id="queryAnalyzerModalAnalyseButton">{{ t('Analyse query') }}</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="analysingLogsModal" tabindex="-1" aria-labelledby="analysingLogsModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="analysingLogsModalLabel">{{ t('Analysing logs') }}</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{{ t('Cancel request') }}"></button>
</div>
<div class="modal-body">
<p>{{ t('Analysing and loading logs. This may take a while.') }}</p>
<div class="spinner-border" role="status">
<span class="visually-hidden">{{ t('Loading…') }}</span>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ t('Cancel request') }}</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="analysingLogsNoDataFoundModal" tabindex="-1" aria-labelledby="analysingLogsNoDataFoundModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="analysingLogsNoDataFoundModalLabel">{{ t('No data found') }}</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{{ t('Close') }}"></button>
</div>
<div class="modal-body">
{{ t('Log analysed, but no data found in this time span.') }}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ t('Close') }}</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="analysingLogsLogDataLoadedModal" tabindex="-1" aria-labelledby="analysingLogsLogDataLoadedModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="analysingLogsLogDataLoadedModalLabel">{{ t('Loading logs') }}</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{{ t('Close') }}"></button>
</div>
<div class="modal-body">
<p>{{ t('Log data loaded. Queries executed in this time span:') }}</p>
<div></div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ t('Close') }}</button>
<button type="button" class="btn btn-primary" id="analysingLogsLogDataLoadedModalJumpButton">{{ t('Jump to the log table') }}</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="serverResponseErrorModal" tabindex="-1" aria-labelledby="serverResponseErrorModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="serverResponseErrorModalLabel">{{ t('Monitor refresh failed') }}</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{{ t('Close') }}"></button>
</div>
<div class="modal-body">
<span aria-label="{{ t('Warning:') }}">{{ get_image('s_attention') }}</span>
{{ t('While requesting new chart data the server returned an invalid response. This is most likely because your session expired. Reloading the page and reentering your credentials should help.') }}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ t('Close') }}</button>
<button type="button" class="btn btn-primary" id="serverResponseErrorModalReloadButton">{{ t('Reload page') }}</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="incompatibleMonitorConfigModal" tabindex="-1" aria-labelledby="incompatibleMonitorConfigModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="incompatibleMonitorConfigModalLabel">{{ t('Local monitor configuration incompatible!') }}</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{{ t('Close') }}"></button>
</div>
<div class="modal-body">
<span aria-label="{{ t('Warning:') }}">{{ get_image('s_attention') }}</span>
{{ t('The chart arrangement configuration in your browsers local storage is not compatible anymore to the newer version of the monitor dialog. It is very likely that your current configuration will not work anymore. Please reset your configuration to default in the [em]Settings[/em] menu.')|sanitize }}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ t('Close') }}</button>
</div>
</div>
</div>
</div>
<div class="clearfloat"></div>

View File

@ -73,4 +73,39 @@
</tbody>
</table>
</form>
<div class="modal fade" id="triggersEditorModal" tabindex="-1" aria-labelledby="triggersEditorModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="triggersEditorModalLabel">{{ t('Trigger editor') }}</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{{ t('Close') }}"></button>
</div>
<div class="modal-body">
<div class="spinner-border" role="status">
<span class="visually-hidden">{{ t('Loading…') }}</span>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ t('Close') }}</button>
<button type="button" class="btn btn-primary" id="triggersEditorModalSaveButton">{{ t('Save changes') }}</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="triggersExportModal" tabindex="-1" aria-labelledby="triggersExportModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="triggersExportModalLabel">{{ t('Export trigger') }}</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="{{ t('Close') }}"></button>
</div>
<div class="modal-body"></div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">{{ t('Close') }}</button>
</div>
</div>
</div>
</div>
</div>

View File

@ -172,15 +172,6 @@ final class JavaScriptMessagesController implements InvocableController
'numberOfStatements' => __('Number of statements'),
/* server status monitor */
'strIncompatibleMonitorConfig' => __('Local monitor configuration incompatible!'),
'strIncompatibleMonitorConfigDescription' => __(
'The chart arrangement configuration in your browsers local storage is not '
. 'compatible anymore to the newer version of the monitor dialog. It is very '
. 'likely that your current configuration will not work anymore. Please reset '
. 'your configuration to default in the <i>Settings</i> menu.',
),
'strQueryCacheEfficiency' => __('Query cache efficiency'),
'strQueryCacheUsage' => __('Query cache usage'),
'strQueryCacheUsed' => __('Query cache used'),
@ -265,12 +256,7 @@ final class JavaScriptMessagesController implements InvocableController
'strDividedBy' => __('Divided by %s'),
'strUnit' => __('Unit'),
'strFromSlowLog' => __('From slow log'),
'strFromGeneralLog' => __('From general log'),
'strServerLogError' => __('The database name is not known for this query in the server\'s logs.'),
'strAnalysingLogsTitle' => __('Analysing logs'),
'strAnalysingLogs' => __('Analysing & loading logs. This may take a while.'),
'strCancelRequest' => __('Cancel request'),
'strCountColumnExplanation' => __(
'This column shows the amount of identical queries that are grouped together. '
. 'However only the SQL query itself has been used as a grouping criteria, so '
@ -281,11 +267,6 @@ final class JavaScriptMessagesController implements InvocableController
. 'same table are also being grouped together, disregarding of the inserted '
. 'data.',
),
'strLogDataLoaded' => __('Log data loaded. Queries executed in this time span:'),
'strJumpToTable' => __('Jump to Log table'),
'strNoDataFoundTitle' => __('No data found'),
'strNoDataFound' => __('Log analysed, but no data found in this time span.'),
'strAnalyzing' => __('Analyzing…'),
'strExplainOutput' => __('Explain output'),
@ -309,30 +290,17 @@ final class JavaScriptMessagesController implements InvocableController
'strSumRows' => __('Sum of grouped rows:'),
'strTotal' => __('Total:'),
'strLoadingLogs' => __('Loading logs'),
'strRefreshFailed' => __('Monitor refresh failed'),
'strInvalidResponseExplanation' => __(
'While requesting new chart data the server returned an invalid response. This '
. 'is most likely because your session expired. Reloading the page and '
. 'reentering your credentials should help.',
),
'strReloadPage' => __('Reload page'),
'strAffectedRows' => __('Affected rows:'),
'strFailedParsingConfig' => __('Failed parsing config file. It doesn\'t seem to be valid JSON code.'),
'strFailedBuildingGrid' => __(
'Failed building chart grid with imported config. Resetting to default config…',
),
'strImport' => __('Import'),
'strImportDialogTitle' => __('Import monitor configuration'),
'strImportDialogMessage' => __('Please select the file you want to import:'),
'strTableNameDialogMessage' => __('Please enter a valid table name.'),
'strDBNameDialogMessage' => __('Please enter a valid database name.'),
'strNoImportFile' => __('No files available on server for import!'),
'strAnalyzeQuery' => __('Analyse query'),
/* For query editor */
'strFormatting' => __('Formatting SQL…'),
'strNoParam' => __('No parameters found!'),
@ -391,6 +359,8 @@ final class JavaScriptMessagesController implements InvocableController
'strExport' => __('Export'),
'NoExportable' => __('No routine is exportable. Required privileges may be lacking.'),
'strRoutine' => __('Routine'),
'strTrigger' => __('Trigger'),
'strEvent' => __('Event'),
/* For ENUM/SET editor*/
'enum_columnVals' => __('Values for column %s'),

View File

@ -104,16 +104,7 @@ class EventsTest extends TestBase
$proc = 'UPDATE ' . $this->databaseName . '.`test_table` SET val=val+1';
$this->typeInTextArea($proc);
$action = $this->webDriver->action();
// Resize the too big text box to access Go button
$element = $this->byXPath('//*[@class="ui-resizable-handle ui-resizable-s"]');
$action->moveToElement($element)
->clickAndHold()
->moveByOffset(0, -120)// Resize
->click()// Click to free the mouse
->perform();
$this->byCssSelector('div.ui-dialog-buttonset button:nth-child(1)')->click();
$this->byId('eventsEditorModalSaveButton')->click();
$success = $this->waitForElement('cssSelector', '.alert-success');
self::assertStringContainsString('Event `test_event` has been created', $success->getText());
@ -172,7 +163,7 @@ class EventsTest extends TestBase
$this->byName('item_interval_value')->clear();
$this->byName('item_interval_value')->sendKeys('2');
$this->byCssSelector('div.ui-dialog-buttonset button:nth-child(1)')->click();
$this->byId('eventsEditorModalSaveButton')->click();
$success = $this->waitForElement('cssSelector', '.alert-success');
self::assertStringContainsString('Event `test_event` has been modified', $success->getText());

View File

@ -91,7 +91,7 @@ class TriggersTest extends TestBase
$proc = 'UPDATE ' . $this->databaseName . '.`test_table2` SET val=val+1';
$this->typeInTextArea($proc);
$this->byCssSelector('div.ui-dialog-buttonset button:nth-child(1)')->click();
$this->byId('triggersEditorModalSaveButton')->click();
$success = $this->waitForElement('cssSelector', '.alert-success');
self::assertStringContainsString('Trigger `test_trigger` has been created', $success->getText());
@ -142,7 +142,7 @@ class TriggersTest extends TestBase
$proc = 'UPDATE ' . $this->databaseName . '.`test_table2` SET val=val+10';
$this->typeInTextArea($proc);
$this->byCssSelector('div.ui-dialog-buttonset button:nth-child(1)')->click();
$this->byId('triggersEditorModalSaveButton')->click();
$success = $this->waitForElement('cssSelector', '.alert-success');
self::assertStringContainsString('Trigger `test_trigger` has been modified', $success->getText());

View File

@ -181,6 +181,41 @@ final class EventsControllerTest extends AbstractTestCase
</div>
</div>
</div>
<div class="modal fade" id="eventsEditorModal" tabindex="-1" aria-labelledby="eventsEditorModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="eventsEditorModalLabel">Event editor</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="spinner-border" role="status">
<span class="visually-hidden">Loading…</span>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" id="eventsEditorModalSaveButton">Save changes</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="eventsExportModal" tabindex="-1" aria-labelledby="eventsExportModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="eventsExportModalLabel">Export event</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body"></div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>
HTML;
@ -307,6 +342,41 @@ HTML;
</div>
</div>
</div>
<div class="modal fade" id="eventsEditorModal" tabindex="-1" aria-labelledby="eventsEditorModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="eventsEditorModalLabel">Event editor</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="spinner-border" role="status">
<span class="visually-hidden">Loading…</span>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" id="eventsEditorModalSaveButton">Save changes</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="eventsExportModal" tabindex="-1" aria-labelledby="eventsExportModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="eventsExportModalLabel">Export event</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body"></div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>
HTML;

View File

@ -79,11 +79,8 @@ class MonitorControllerTest extends AbstractTestCase
);
self::assertStringContainsString('<option>3</option>', $html);
self::assertStringContainsString(
__('Monitor Instructions'),
$html,
);
self::assertStringContainsString('monitorInstructionsDialog', $html);
self::assertStringContainsString('System monitor instructions', $html);
self::assertStringContainsString('monitorInstructionsModal', $html);
self::assertStringContainsString('<div class="modal fade" id="addChartModal"', $html);
self::assertStringContainsString('<div id="chartVariableSettings">', $html);

View File

@ -149,6 +149,41 @@ final class IndexControllerTest extends AbstractTestCase
</tbody>
</table>
</form>
<div class="modal fade" id="triggersEditorModal" tabindex="-1" aria-labelledby="triggersEditorModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="triggersEditorModalLabel">Trigger editor</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="spinner-border" role="status">
<span class="visually-hidden">Loading…</span>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" id="triggersEditorModalSaveButton">Save changes</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="triggersExportModal" tabindex="-1" aria-labelledby="triggersExportModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="triggersExportModalLabel">Export trigger</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body"></div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>
HTML;
@ -237,6 +272,41 @@ HTML;
<tr class="hide"><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr> </tbody>
</table>
</form>
<div class="modal fade" id="triggersEditorModal" tabindex="-1" aria-labelledby="triggersEditorModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="triggersEditorModalLabel">Trigger editor</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div class="spinner-border" role="status">
<span class="visually-hidden">Loading…</span>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" id="triggersEditorModalSaveButton">Save changes</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="triggersExportModal" tabindex="-1" aria-labelledby="triggersExportModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="triggersExportModalLabel">Export trigger</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body"></div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>
HTML;