Remove Alertify from pgAdmin completely. Fixes #7619

This commit is contained in:
Akshay Joshi
2022-09-08 15:16:48 +05:30
parent e1942d8c9e
commit 18b77f15dd
149 changed files with 634 additions and 1573 deletions

View File

@@ -1,5 +1,3 @@
@import 'node_modules/alertifyjs/build/css/alertify.css';
@import 'node_modules/alertifyjs/build/css/themes/bootstrap.css';
@import 'node_modules/@fortawesome/fontawesome-free/css/all.css';
@import 'node_modules/bootstrap-datepicker/dist/css/bootstrap-datepicker3.css';
@import 'node_modules/tempusdominus-bootstrap-4/build/css/tempusdominus-bootstrap-4.css';

View File

@@ -26,7 +26,7 @@ import RenamePanelContent from './RenamePanelContent';
function mountDialog(title, getDialogContent, docker=undefined, width, height) {
// Register dialog panel
var panel;
let panel;
if (docker) {
pgAdmin.Browser.Node.registerUtilityPanel(docker);
panel = pgAdmin.Browser.Node.addUtilityPanel(width||pgAdmin.Browser.stdW.md, height||undefined, docker);
@@ -35,7 +35,7 @@ function mountDialog(title, getDialogContent, docker=undefined, width, height) {
panel = pgAdmin.Browser.Node.addUtilityPanel(width||pgAdmin.Browser.stdW.md);
}
var j = panel.$container.find('.obj_properties').first();
let j = panel.$container.find('.obj_properties').first();
panel.title(title);
const onClose = ()=> {
@@ -61,7 +61,7 @@ function mountDialog(title, getDialogContent, docker=undefined, width, height) {
// This functions is used to show the connect server password dialog.
export function showServerPassword() {
var title = arguments[0],
let title = arguments[0],
formJson = arguments[1],
nodeObj = arguments[2],
nodeData = arguments[3],
@@ -83,7 +83,7 @@ export function showServerPassword() {
data={formJson}
onOK={(formData)=>{
const api = getApiInstance();
var _url = nodeObj.generate_url(itemNodeData, 'connect', nodeData, true);
let _url = nodeObj.generate_url(itemNodeData, 'connect', nodeData, true);
if (!status) {
treeNodeInfo.setLeaf(itemNodeData);
treeNodeInfo.removeIcon(itemNodeData);
@@ -112,7 +112,7 @@ export function showServerPassword() {
// This functions is used to show the connect server password dialog when
// launch from Schema Diff tool.
export function showSchemaDiffServerPassword() {
var docker = arguments[0],
let docker = arguments[0],
title = arguments[1],
formJson = arguments[2],
serverID = arguments[3],
@@ -132,7 +132,7 @@ export function showSchemaDiffServerPassword() {
data={formJson}
onOK={(formData)=>{
const api = getApiInstance();
var _url = url_for('schema_diff.connect_server', {'sid': serverID});
let _url = url_for('schema_diff.connect_server', {'sid': serverID});
api.post(_url, formData)
.then(res=>{
@@ -191,7 +191,7 @@ export function showMasterPassword(isPWDPresent, errmsg, masterpass_callback_que
gettext('This will remove all the saved passwords. This will also remove established connections to '
+ 'the server and you may need to reconnect again. Do you wish to continue?'),
function() {
var _url = url_for('browser.reset_master_password');
let _url = url_for('browser.reset_master_password');
api.delete(_url)
.then(() => {
@@ -219,7 +219,7 @@ export function showMasterPassword(isPWDPresent, errmsg, masterpass_callback_que
}
export function showChangeServerPassword() {
var title = arguments[0],
let title = arguments[0],
nodeData = arguments[1],
nodeObj = arguments[2],
itemNodeData = arguments[3],
@@ -234,7 +234,7 @@ export function showChangeServerPassword() {
onSave={(isNew, data)=>{
return new Promise((resolve, reject)=>{
const api = getApiInstance();
var _url = nodeObj.generate_url(itemNodeData, 'change_password', nodeData, true);
let _url = nodeObj.generate_url(itemNodeData, 'change_password', nodeData, true);
api.post(_url, data)
.then(({data: respData})=>{
@@ -265,7 +265,7 @@ export function showChangeServerPassword() {
}
export function showNamedRestorePoint() {
var title = arguments[0],
let title = arguments[0],
nodeData = arguments[1],
nodeObj = arguments[2],
itemNodeData = arguments[3];
@@ -281,7 +281,7 @@ export function showNamedRestorePoint() {
}}
onOK={(formData)=>{
const api = getApiInstance();
var _url = nodeObj.generate_url(itemNodeData, 'restore_point', nodeData, true);
let _url = nodeObj.generate_url(itemNodeData, 'restore_point', nodeData, true);
api.post(_url, formData)
.then(res=>{
@@ -298,7 +298,7 @@ export function showNamedRestorePoint() {
}
export function showChangeOwnership() {
var title = arguments[0],
let title = arguments[0],
userList = arguments[1],
noOfSharedServers = arguments[2],
deletedUser = arguments[3],

View File

@@ -24,20 +24,20 @@ import clsx from 'clsx';
import PropTypes from 'prop-types';
// Some predefined constants used to calculate image location and its border
var pWIDTH = 100.;
var pHEIGHT = 100.;
var IMAGE_WIDTH = 50;
var IMAGE_HEIGHT = 50;
var ARROW_WIDTH = 10,
let pWIDTH = 100.;
let pHEIGHT = 100.;
let IMAGE_WIDTH = 50;
let IMAGE_HEIGHT = 50;
let ARROW_WIDTH = 10,
ARROW_HEIGHT = 10;
var TXT_ALIGN = 5,
let TXT_ALIGN = 5,
TXT_SIZE = '15px';
var xMargin = 25,
let xMargin = 25,
yMargin = 25;
var MIN_ZOOM_FACTOR = 0.3,
let MIN_ZOOM_FACTOR = 0.3,
MAX_ZOOM_FACTOR = 2,
INIT_ZOOM_FACTOR = 1;
var ZOOM_RATIO = 0.05;
let ZOOM_RATIO = 0.05;
const AUXILIARY_KEYS = ['image', 'Plans', 'level', 'image_text', 'xpos', 'ypos', 'width', 'height', 'total_time', 'parent_node', '_serial', 'arr_id'];
@@ -66,11 +66,11 @@ PolyLine.propTypes = {
function Multitext({currentXpos, currentYpos, label, maxWidth}) {
const theme = useTheme();
let abc = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
var xmlns = 'http://www.w3.org/2000/svg';
var svgElem = document.createElementNS(xmlns, 'svg');
let xmlns = 'http://www.w3.org/2000/svg';
let svgElem = document.createElementNS(xmlns, 'svg');
svgElem.setAttributeNS(xmlns, 'height', '100%');
svgElem.setAttributeNS(xmlns, 'width', '100%');
var text = document.createElementNS(xmlns, 'text');
let text = document.createElementNS(xmlns, 'text');
text.innerHTML = abc;
text.setAttributeNS(xmlns, 'x', 0);
text.setAttributeNS(xmlns, 'y', 0);
@@ -88,11 +88,11 @@ function Multitext({currentXpos, currentYpos, label, maxWidth}) {
* Find letter width in pixels and
* index from where the text should be broken
*/
var letterWidth = text.getBBox().width / abc.length,
let letterWidth = text.getBBox().width / abc.length,
wordBreakIndex = Math.round((maxWidth / letterWidth)) - 1;
svgElem.remove();
var words = label.split(' '),
let words = label.split(' '),
widthSoFar = 0,
lines = [],
currLine = '',
@@ -102,7 +102,7 @@ function Multitext({currentXpos, currentYpos, label, maxWidth}) {
* the max-width boundary.
*/
splitTextInMultiLine = function(leading, so_far, line) {
var l = line.length,
let l = line.length,
res = [];
if (l == 0)
@@ -126,8 +126,8 @@ function Multitext({currentXpos, currentYpos, label, maxWidth}) {
return res;
};
for (var i = 0; i < words.length; i++) {
var tmpArr = splitTextInMultiLine(
for (let i = 0; i < words.length; i++) {
let tmpArr = splitTextInMultiLine(
currLine, widthSoFar, words[i]
);

View File

@@ -27,11 +27,11 @@ const useStyles = makeStyles((theme)=>({
}));
// Some predefined constants used to calculate image location and its border
var pWIDTH = 100.;
var pHEIGHT = 100.;
var offsetX = 200,
let pWIDTH = 100.;
let pHEIGHT = 100.;
let offsetX = 200,
offsetY = 60;
var xMargin = 25,
let xMargin = 25,
yMargin = 25;
const DEFAULT_ARROW_SIZE = 2;
@@ -154,7 +154,7 @@ function nodeExplainTableData(_planData, _ctx) {
}
if ('Peak Memory Usage' in _planData) {
var buffer = [
let buffer = [
'<strong>' + gettext('Buckets') + '</strong>:', _.escape(_planData['Hash Buckets']),
'<strong>' + gettext('Batches') + '</strong>:', _.escape(_planData['Hash Batches']),
'<strong>' + gettext('Memory Usage') + '</strong>:', _.escape(_planData['Peak Memory Usage']), 'kB',
@@ -246,7 +246,7 @@ function parseExplainTableData(plan, ctx) {
}
function parsePlan(data, ctx) {
var idx = 1,
let idx = 1,
lvl = data.level = data.level || [idx],
plans = [],
nodeType = data['Node Type'],
@@ -292,7 +292,7 @@ function parsePlan(data, ctx) {
nodeType = nodeType.substring(0, 7);
// Get the image information for current node
var mappedImage = (_.isFunction(ImageMapper[nodeType]) &&
let mappedImage = (_.isFunction(ImageMapper[nodeType]) &&
ImageMapper[nodeType].apply(undefined, [data])) ||
ImageMapper[nodeType] || {
'image': 'ex_unknown.svg',
@@ -378,7 +378,7 @@ function parsePlan(data, ctx) {
}
}
var childHeight = plan.height;
let childHeight = plan.height;
if (idx !== 1) {
data['height'] = data['height'] + childHeight + offsetY;

View File

@@ -1,316 +0,0 @@
/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2022, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
define([
'sources/gettext', 'alertify', 'jquery', 'sources/utils',
], function(gettext, alertify, $, commonUtils) {
alertify.defaults.transition = 'zoom';
alertify.defaults.theme.ok = 'btn btn-primary fa fa-lg fa-check pg-alertify-button';
alertify.defaults.theme.cancel = 'btn btn-secondary fa fa-lg fa-times pg-alertify-button';
alertify.defaults.theme.input = 'form-control';
alertify.defaults.closable = false;
var alertifyDialogResized = function(stop) {
var self = this;
if (stop) {
self.pgResizeRecursion = false;
}
if (self.pgResizeTimeout) {
return;
}
self.pgResizeTimeout = setTimeout(
function() {
var $el = $(this.elements.dialog),
w = $el.width(),
elAttr = 'xs';
this.pgResizeTimeout = null;
/** Calculations based on https://getbootstrap.com/docs/4.1/layout/grid/#grid-options **/
if (w >= 480) {
elAttr = 'sm';
}
if (w >= 768) {
elAttr = 'md';
}
if (w >= 992) {
elAttr = 'lg';
}
if (w >=1200) {
elAttr = 'xl';
}
$el.attr('el', elAttr);
}.bind(self),
100
);
};
var alertifyDialogStartResizing = function(start) {
var self = this;
if (start) {
self.pgResizeRecursion = true;
}
setTimeout(
function() {
alertifyDialogResized.apply(self);
if (self.pgResizeRecursion) {
alertifyDialogStartResizing.apply(self, [false]);
}
}, 100
);
};
alertify.pgDialogBuild = function() {
this.set('onshow', function() {
this.elements.dialog.classList.add('pg-el-container');
$(this.elements.commands.close).attr('title', gettext('Close'));
$(this.elements.commands.maximize).attr('title', gettext('Maximize'));
$(this.elements.commands.close).attr('aria-label', gettext('Close'));
$(this.elements.commands.maximize).attr('aria-label', gettext('Maximize'));
alertifyDialogResized.apply(this, arguments);
let _self = this;
let cmds = Object.values(this.elements.commands);
$(cmds).on('keydown', 'button', (event) => {
if (event.shiftKey && event.keyCode == 9 && $(this).nextAll('button:not([disabled])').length == 0){
let container = $(_self.elements.footer);
commonUtils.findAndSetFocus(container.find('button:not([disabled]):last'));
}
});
});
this.set('onresize', alertifyDialogStartResizing.bind(this, true));
this.set('onresized', alertifyDialogResized.bind(this, true));
this.set('onmaximized', alertifyDialogResized);
this.set('onrestored', alertifyDialogResized);
/* Set the key to null if it is not defined
* When Browser autofill drop down value is clicked it raises a keyup event
* with undefined keyCode. The undefined keyCode matches the undefined key
* of alertify and triggers the button
*/
for(let btn_val of this.__internal.buttons) {
if(_.isUndefined(btn_val['key'])) {
btn_val['key'] = null;
}
}
let self = this;
$(this.elements.footer).on('keydown', 'button', function(event) {
if (!event.shiftKey && event.keyCode == 9 && $(this).nextAll('button:not([disabled])').length == 0) {
// set focus back to first editable input element of current active tab once we cycle through all enabled buttons.
commonUtils.findAndSetFocus($(self.elements.dialog));
return false;
}
});
};
alertify.pgHandleItemError = function(xhr, error, message, args) {
var pgBrowser = window.pgAdmin.Browser;
if (!xhr || !pgBrowser) {
return;
}
var contentType = xhr.getResponseHeader('Content-Type'),
jsonResp = contentType &&
contentType.indexOf('application/json') == 0 &&
JSON.parse(xhr.responseText);
if (
jsonResp && (
xhr.status == 503 ? (
jsonResp.info == 'CONNECTION_LOST' &&
'server' in args.info && jsonResp.data.sid >= 0 &&
jsonResp.data.sid == args.info.server._id
) : (
xhr.status == 428 &&
jsonResp.errormsg &&
jsonResp.errormsg == gettext('Connection to the server has been lost.')
)
)
) {
if (
args.preHandleConnectionLost &&
typeof(args.preHandleConnectionLost) == 'function'
) {
args.preHandleConnectionLost.apply(this, arguments);
}
// Check the status of the maintenance server connection.
var server = pgBrowser.Nodes['server'],
ctx = {
resp: jsonResp,
xhr: xhr,
args: args,
},
reconnectServer = function() {
var ctx_local = this,
onServerConnect = function(_sid, _i, _d) {
// Yay - server is reconnected.
if (this.args.info.server._id == _sid) {
pgBrowser.Events.off(
'pgadmin:server:connected', onServerConnect
);
pgBrowser.Events.off(
'pgadmin:server:connect:cancelled', onConnectCancel
);
// Do we need to connect the disconnected server now?
if (
this.resp.data.database &&
this.resp.data.database != _d.db
) {
// Server is connected now, we will need to inform the
// database to connect it now.
pgBrowser.Events.trigger(
'pgadmin:database:connection:lost', this.args.item,
this.resp, true
);
}
}
}.bind(ctx_local),
onConnectCancel = function(_sid, _item, _data) {
// User has cancelled the operation in between.
if (_sid == this.args.info.server.id) {
pgBrowser.Events.off('pgadmin:server:connected', onServerConnect);
pgBrowser.Events.off('pgadmin:server:connect:cancelled', onConnectCancel);
// Connection to the database will also be cancelled
pgBrowser.Events.trigger(
'pgadmin:database:connect:cancelled', _sid,
this.resp.data.database || _data.db, _item, _data
);
}
}.bind(ctx_local);
pgBrowser.Events.on('pgadmin:server:connected', onServerConnect);
pgBrowser.Events.on('pgadmin:server:connect:cancelled', onConnectCancel);
// Connection to the server has been lost, we need to inform the
// server first to take the action first.
pgBrowser.Events.trigger(
'pgadmin:server:connection:lost', this.args.item, this.resp
);
}.bind(ctx);
$.ajax({
url: server.generate_url(
null, 'connect', args.info.server, true, args.info
),
dataType: 'json',
})
.done(function(res) {
if (res.success && 'connected' in res.data) {
if (res.data.connected) {
// Server is connected, but - the connection with the
// particular database has been lost.
pgBrowser.Events.trigger(
'pgadmin:database:connection:lost', args.item, jsonResp
);
return;
}
}
// Serever was not connected, we should first try to connect
// the server.
reconnectServer();
})
.fail(function() {
reconnectServer();
});
return true;
} else if (jsonResp && jsonResp.info == 'CRYPTKEY_MISSING' && xhr.status == 503) {
/* Suppress the error here and handle in Alertify.pgNotifier wherever
* required, as it has callback option
*/
return false;
}
return false;
};
// Confirm dialogue: Set title attribute
alertify.confirm().set({
onshow:function() {
$(this.elements.commands.close).attr('title', gettext('Close'));
$(this.elements.commands.maximize).attr('title', gettext('Maximize'));
$(this.elements.content).addClass('ajs-wrap-text');
$(this.elements.header).attr('id', 'confirm-dialog-header');
$(this.elements.body).attr('id', 'confirm-dialog-body');
$(this.elements.dialog).attr({
role: 'alertdialog',
'aria-modal': 'true',
'aria-labelledby': 'confirm-dialog-header',
'aria-describedby': 'confirm-dialog-body',
});
},
reverseButtons: true,
});
alertify.prompt().set({
reverseButtons: true,
});
alertify.alert().set({
onshow:function() {
$(this.elements.header).attr('id', 'alert-dialog-header');
$(this.elements.body).attr('id', 'alert-dialog-body');
$(this.elements.modal).attr({
role: 'alertdialog',
'aria-modal': 'true',
'aria-labelledby': 'alert-dialog-header',
'aria-describedby': 'alert-dialog-body',
});
},
});
/* Suppress the enter key events occurring from select2 boxes
* so that the dialog does not close.
* Alertify listens to keyup events on the body element unfortunately
* instead of alertify dialog
*/
$('body').off('keyup').on('keyup', function(ev){
if(ev.which === 13 || ev.which === 27) {
let suppressForClasses = ['select2-selection', 'select2-search__field'];
let $el = $(ev.target);
for(let class_val of suppressForClasses){
if($el.hasClass(class_val)){
ev.preventDefault();
ev.stopImmediatePropagation();
ev.stopPropagation();
break;
}
}
let el_name = ev.target.name;
if(el_name == 'key'){
let $parentDiv = $el.closest('.value'),
$nextField = $parentDiv.find('.shift .btn-checkbox');
if ($nextField.length == 0) {
$nextField = $el.closest('.value').next().find('input.form-control');
}
if ($nextField.length) {
$nextField.focus();
ev.preventDefault();
ev.stopImmediatePropagation();
ev.stopPropagation();
}
}
}
});
return alertify;
});

View File

@@ -1,121 +0,0 @@
/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2022, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import gettext from '../gettext';
import {DialogFactory} from './dialog_factory';
import Backform from '../backform.pgadmin';
/**
* This class can be extended to create new dialog boxes.
* Examples of this can be found in:
* `web/pgadmin/static/js/backup/backup_dialog.js`
*
* Do not forget to add the new Dialog type to the `DialogFactory`
*/
export class Dialog {
constructor(errorAlertTitle,
dialogContainerSelector,
pgBrowser, $, alertify, DialogModel,
backform = Backform) {
this.errorAlertTitle = errorAlertTitle;
this.alertify = alertify;
this.pgBrowser = pgBrowser;
this.jquery = $;
this.dialogModel = DialogModel;
this.backform = backform;
this.dialogContainerSelector = dialogContainerSelector;
}
retrieveAncestorOfTypeServer(item) {
let serverInformation = null;
let treeItem = item || this.pgBrowser.tree.selected();
let treeNode = this.pgBrowser.tree.findNodeByDomElement(treeItem);
if (treeNode) {
let nodeData;
let databaseNode = treeNode.ancestorNode(
(node) => {
nodeData = node.getData();
return (nodeData._type === 'database');
}
);
let isServerNode = (node) => {
nodeData = node.getData();
return nodeData._type === 'server';
};
if (databaseNode !== null) {
if (nodeData._label.indexOf('=') >= 0) {
this.alertify.alert(
gettext(this.errorAlertTitle),
gettext(
'Databases with = symbols in the name cannot be backed up or restored using this utility.'
)
);
} else {
if (databaseNode.anyParent(isServerNode))
serverInformation = nodeData;
}
} else {
if (treeNode.anyFamilyMember(isServerNode))
serverInformation = nodeData;
}
}
if (serverInformation === null) {
this.alertify.alert(
gettext(this.errorAlertTitle),
gettext('Please select server or child node from the browser tree.')
);
}
return serverInformation;
}
dialogName() {
return undefined;
}
createOrGetDialog(dialogTitle, typeOfDialog) {
const dialogName = this.dialogName(typeOfDialog);
if (!this.alertify[dialogName]) {
const self = this;
this.alertify.dialog(dialogName, function factory() {
return self.dialogFactory(dialogTitle, typeOfDialog);
});
}
return this.alertify[dialogName];
}
dialogFactory(dialogTitle, typeOfDialog) {
const factory = new DialogFactory(
this.pgBrowser,
this.jquery,
this.alertify,
this.dialogModel,
this.backform,
this.dialogContainerSelector);
return factory.create(dialogTitle, typeOfDialog);
}
canExecuteOnCurrentDatabase(treeItem) {
const treeInfo = this.pgBrowser.tree.getTreeNodeHierarchy(treeItem);
if (treeInfo.database && treeInfo.database._label.indexOf('=') >= 0) {
this.alertify.alert(
gettext(this.errorAlertTitle),
gettext('Databases with = symbols in the name cannot be backed up or restored using this utility.')
);
return false;
}
return true;
}
}

View File

@@ -1,41 +0,0 @@
/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2022, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import SearchObjectsDialogWrapper from '../../../tools/search_objects/static/js/search_objects_dialog_wrapper';
export class DialogFactory {
constructor(pgBrowser, $,
alertify, DialogModel,
backform, dialogContainerSelector) {
this.pgBrowser = pgBrowser;
this.jquery = $;
this.alertify = alertify;
this.dialogModel = DialogModel;
this.backform = backform;
this.dialogContainerSelector = dialogContainerSelector;
}
create(dialogTitle, typeOfDialog) {
if (typeOfDialog === 'restore') {
return this.createRestoreDialog(dialogTitle, typeOfDialog);
} else if (typeOfDialog === 'search_objects') {
return this.createSearchObjectsDialog(dialogTitle, typeOfDialog);
}
}
createSearchObjectsDialog(dialogTitle, typeOfDialog) {
return new SearchObjectsDialogWrapper(
this.dialogContainerSelector, dialogTitle, typeOfDialog,
this.jquery,
this.pgBrowser,
this.alertify,
this.dialogModel,
this.backform);
}
}

View File

@@ -1,72 +0,0 @@
/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2022, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import * as commonUtils from '../utils';
import $ from 'jquery';
export class DialogWrapper {
constructor(
dialogContainerSelector, dialogTitle, jquery, pgBrowser,
alertify, dialogModel, backform) {
this.hooks = {
onclose: function () {
if (this.view) {
this.view.remove({
data: true,
internal: true,
silent: true,
});
}
},
};
this.dialogContainerSelector = dialogContainerSelector;
this.dialogTitle = dialogTitle;
this.jquery = jquery;
this.pgBrowser = pgBrowser;
this.alertify = alertify;
this.dialogModel = dialogModel;
this.backform = backform;
}
build() {
this.alertify.pgDialogBuild.apply(this);
}
wasHelpButtonPressed(e) {
return e.button.element.name === 'dialog_help'
|| e.button.element.name === 'object_help';
}
getSelectedNodeData(selectedTreeNode) {
if (!this.isNodeSelected(selectedTreeNode)) {
return undefined;
}
const treeNodeData = selectedTreeNode.getData();
if (treeNodeData) {
return treeNodeData;
}
return undefined;
}
focusOnDialog(alertifyDialog) {
let backform_tab = $(alertifyDialog.elements.body).find('.backform-tab');
backform_tab.attr('tabindex', -1);
this.pgBrowser.keyboardNavigation.getDialogTabNavigator($(alertifyDialog.elements.dialog));
let container = backform_tab.find('.tab-content:first > .tab-pane.active:first');
if(container.length === 0 && alertifyDialog.elements.content.innerHTML) {
container = $(alertifyDialog.elements.content);
}
commonUtils.findAndSetFocus(container);
}
isNodeSelected(selectedTreeNode) {
return selectedTreeNode;
}
}

View File

@@ -7,13 +7,15 @@
//
//////////////////////////////////////////////////////////////
import { calcFontSize } from './utils';
define([
'sources/gettext', 'underscore', 'jquery',
'backbone', 'backform', 'backgrid', 'codemirror', 'sources/sqleditor_utils',
'backbone', 'backform', 'backgrid', 'codemirror',
'sources/keyboard_shortcuts', 'sources/window', 'sources/select2/configure_show_on_scroll',
'color-picker', 'pgadmin.backgrid', 'select2', 'bootstrap.toggle',
], function(gettext, _, $, Backbone, Backform, Backgrid, CodeMirror,
SqlEditorUtils, keyboardShortcuts, pgWindow, configure_show_on_scroll,
keyboardShortcuts, pgWindow, configure_show_on_scroll,
Pickr) {
var pgAdmin = (window.pgAdmin = window.pgAdmin || {}),
@@ -1889,7 +1891,7 @@ define([
let sqlEditPreferences = pgAdmin.Browser.get_preferences_for_module('sqleditor');
$(self.sqlCtrl.getWrapperElement()).css(
'font-size',SqlEditorUtils.calcFontSize(sqlEditPreferences.sql_font_size)
'font-size', calcFontSize(sqlEditPreferences.sql_font_size)
);
self.sqlCtrl.setOption('tabSize', sqlEditPreferences.tab_size);
self.sqlCtrl.setOption('lineWrapping', sqlEditPreferences.wrap_code);
@@ -2623,7 +2625,7 @@ define([
let sqlEditPreferences = browser.get_preferences_for_module('sqleditor');
$(self.sqlCtrl.getWrapperElement()).css(
'font-size',SqlEditorUtils.calcFontSize(sqlEditPreferences.sql_font_size)
'font-size', calcFontSize(sqlEditPreferences.sql_font_size)
);
self.sqlCtrl.setOption('indentWithTabs', !sqlEditPreferences.use_spaces);
self.sqlCtrl.setOption('indentUnit', sqlEditPreferences.tab_size);

View File

@@ -10,11 +10,11 @@
import Notify from '../../static/js/helpers/Notifier';
define([
'sources/gettext', 'underscore', 'jquery', 'backbone', 'backform', 'backgrid', 'alertify',
'sources/gettext', 'underscore', 'jquery', 'backbone', 'backform', 'backgrid',
'moment', 'bignumber', 'codemirror', 'sources/utils', 'sources/keyboard_shortcuts', 'sources/select2/configure_show_on_scroll',
'sources/window', 'bootstrap.datetimepicker', 'backgrid.filter', 'bootstrap.toggle',
], function(
gettext, _, $, Backbone, Backform, Backgrid, Alertify, moment, BigNumber, CodeMirror,
gettext, _, $, Backbone, Backform, Backgrid, moment, BigNumber, CodeMirror,
commonUtils, keyboardShortcuts, configure_show_on_scroll, pgWindow
) {
/*

View File

@@ -7,13 +7,13 @@
//
//////////////////////////////////////////////////////////////
import _ from 'underscore';
import _ from 'lodash';
function generate_url(baseUrl, treeInfo, actionType, nodeType, pickFunction, itemDataID) {
let ref = '';
_.each(
_.sortBy(
_.pick(treeInfo, pickFunction),
_.pickBy(treeInfo, pickFunction),
function (treeInfoItems) {
return treeInfoItems.priority;
}

View File

@@ -6,9 +6,10 @@
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
import _ from 'lodash';
define(['jquery', 'underscore'],
function ($, _) {
define([],
function () {
return function (pgBrowser, node_type) {
if(_.isUndefined(node_type) || _.isNull(node_type)) {

View File

@@ -843,7 +843,7 @@ export const InputSelect = forwardRef(({
const theme = useTheme();
/* React will always take options var as changed parameter. So,
/* React will always take options let as changed parameter. So,
We cannot run the below effect with options dependency as it will keep on
loading the options. optionsReloadBasis is helpful to avoid repeated
options load. If optionsReloadBasis value changes, then options will be loaded again.

View File

@@ -118,7 +118,7 @@ AlertContent.propTypes = {
};
var Notifier = {
let Notifier = {
success(msg, autoHideDuration = AUTO_HIDE_DURATION) {
this._callNotify(msg, MESSAGE_TYPE.SUCCESS, autoHideDuration);
},
@@ -151,7 +151,7 @@ var Notifier = {
},
pgRespErrorNotify(xhr, error, prefixMsg='') {
var contentType = xhr.getResponseHeader('Content-Type');
let contentType = xhr.getResponseHeader('Content-Type');
if (xhr.status === 410) {
const pgBrowser = window.pgAdmin.Browser;
pgBrowser.report_error(gettext('Error: Object not found - %s.', xhr.statusText), xhr.responseJSON.errormsg);
@@ -162,7 +162,7 @@ var Notifier = {
} else {
if(contentType){
if(contentType.indexOf('application/json') >= 0) {
var resp = JSON.parse(xhr.responseText);
let resp = JSON.parse(xhr.responseText);
error = _.escape(resp.result) || _.escape(resp.errormsg) || gettext('Unknown error');
}
}
@@ -181,7 +181,7 @@ var Notifier = {
},
pgNotifier(type, xhr, promptmsg, onJSONResult) {
var msg = xhr.responseText,
let msg = xhr.responseText,
contentType = xhr.getResponseHeader('Content-Type');
if (xhr.status == 0) {
@@ -191,10 +191,10 @@ var Notifier = {
if (contentType) {
try {
if (contentType.indexOf('application/json') == 0) {
var resp = JSON.parse(msg);
let resp = JSON.parse(msg);
if(resp.info == 'CRYPTKEY_MISSING') {
var pgBrowser = window.pgAdmin.Browser;
let pgBrowser = window.pgAdmin.Browser;
pgBrowser.set_master_password('', ()=> {
if(onJSONResult && typeof(onJSONResult) == 'function') {
onJSONResult('CRYPTKEY_SET');

View File

@@ -1,71 +0,0 @@
//////////////////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2022, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
import $ from 'jquery';
import _ from 'underscore';
import pgWindow from 'sources/window';
function getBrowserInstance() {
return pgWindow.pgAdmin.Browser;
}
function modifyTreeAnimation(pgBrowser, tree) {
let enableTreeAnimation = pgBrowser.get_preference(
'browser', 'enable_acitree_animation'
).value;
if (_.isUndefined(tree)) {
tree = pgBrowser.tree;
}
if(enableTreeAnimation) {
tree.options({
animateRoot: true,
unanimated: false,
show: _.extend(tree.options().show, {duration: 75}),
hide: _.extend(tree.options().hide, {duration: 75}),
view: _.extend(tree.options().view, {duration: 75}),
});
} else {
tree.options({
animateRoot: false,
unanimated: true,
show: _.extend(tree.options().show, {duration: 0}),
hide: _.extend(tree.options().hide, {duration: 0}),
view: _.extend(tree.options().view, {duration: 0}),
});
}
}
function modifyAlertifyAnimation(pgBrowser) {
if(_.isUndefined(pgBrowser) || _.isNull(pgBrowser)) {
pgBrowser = getBrowserInstance();
}
let enableTreeAnimation = pgBrowser.get_preference(
'browser', 'enable_alertify_animation'
).value;
if(enableTreeAnimation) {
$(document).find('body').removeClass('alertify-no-animation');
_.each(document.getElementsByTagName('iframe'), function(frame) {
$(frame.contentDocument).find('body').removeClass('alertify-no-animation');
});
} else {
$(document).find('body').addClass('alertify-no-animation');
_.each(document.getElementsByTagName('iframe'), function(frame) {
$(frame.contentDocument).find('body').addClass('alertify-no-animation');
});
}
}
module.exports = {
modifyTreeAnimation : modifyTreeAnimation,
modifyAlertifyAnimation: modifyAlertifyAnimation,
};

View File

@@ -1,22 +0,0 @@
//////////////////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2022, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
// This file contains common utilities functions used in sqleditor modules
module.exports = {
calcFontSize: function(fontSize) {
if(fontSize) {
fontSize = parseFloat((Math.round(parseFloat(fontSize + 'e+2')) + 'e-2'));
let rounded = Number(fontSize);
if(rounded > 0) {
return rounded + 'em';
}
}
return '1em';
},
};

View File

@@ -7,7 +7,7 @@
//
//////////////////////////////////////////////////////////////
import _ from 'underscore';
import _ from 'lodash';
import $ from 'jquery';
import url_for from 'sources/url_for';
import gettext from 'sources/gettext';

View File

@@ -9,7 +9,7 @@
import * as BrowserFS from 'browserfs'
import pgAdmin from 'sources/pgadmin';
import _ from 'underscore';
import _ from 'lodash';
import { FileType } from 'react-aspen'
import { findInTree } from './tree';

View File

@@ -10,7 +10,7 @@
import * as BrowserFS from 'browserfs'
import url_for from 'sources/url_for';
import pgAdmin from 'sources/pgadmin';
import _ from 'underscore';
import _ from 'lodash';
import { FileType } from 'react-aspen'
import { findInTree } from './tree';

View File

@@ -523,3 +523,138 @@ export function compareSizeVals(val1, val2) {
if(val1 > val2) return 1;
return (val1 < val2 ? -1 : 0);
}
export function calcFontSize(fontSize) {
if(fontSize) {
fontSize = parseFloat((Math.round(parseFloat(fontSize + 'e+2')) + 'e-2'));
let rounded = Number(fontSize);
if(rounded > 0) {
return rounded + 'em';
}
}
return '1em';
}
export function pgHandleItemError(xhr, args) {
var pgBrowser = window.pgAdmin.Browser;
if (!xhr || !pgBrowser) {
return;
}
var contentType = xhr.getResponseHeader('Content-Type'),
jsonResp = contentType &&
contentType.indexOf('application/json') == 0 &&
JSON.parse(xhr.responseText);
if (
jsonResp && (
xhr.status == 503 ? (
jsonResp.info == 'CONNECTION_LOST' &&
'server' in args.info && jsonResp.data.sid >= 0 &&
jsonResp.data.sid == args.info.server._id
) : (
xhr.status == 428 &&
jsonResp.errormsg &&
jsonResp.errormsg == gettext('Connection to the server has been lost.')
)
)
) {
if (
args.preHandleConnectionLost &&
typeof(args.preHandleConnectionLost) == 'function'
) {
args.preHandleConnectionLost.apply(this, arguments);
}
// Check the status of the maintenance server connection.
var server = pgBrowser.Nodes['server'],
ctx = {
resp: jsonResp,
xhr: xhr,
args: args,
},
reconnectServer = function() {
var ctx_local = this,
onServerConnect = function(_sid, _i, _d) {
// Yay - server is reconnected.
if (this.args.info.server._id == _sid) {
pgBrowser.Events.off(
'pgadmin:server:connected', onServerConnect
);
pgBrowser.Events.off(
'pgadmin:server:connect:cancelled', onConnectCancel
);
// Do we need to connect the disconnected server now?
if (
this.resp.data.database &&
this.resp.data.database != _d.db
) {
// Server is connected now, we will need to inform the
// database to connect it now.
pgBrowser.Events.trigger(
'pgadmin:database:connection:lost', this.args.item,
this.resp, true
);
}
}
}.bind(ctx_local),
onConnectCancel = function(_sid, _item, _data) {
// User has cancelled the operation in between.
if (_sid == this.args.info.server.id) {
pgBrowser.Events.off('pgadmin:server:connected', onServerConnect);
pgBrowser.Events.off('pgadmin:server:connect:cancelled', onConnectCancel);
// Connection to the database will also be cancelled
pgBrowser.Events.trigger(
'pgadmin:database:connect:cancelled', _sid,
this.resp.data.database || _data.db, _item, _data
);
}
}.bind(ctx_local);
pgBrowser.Events.on('pgadmin:server:connected', onServerConnect);
pgBrowser.Events.on('pgadmin:server:connect:cancelled', onConnectCancel);
// Connection to the server has been lost, we need to inform the
// server first to take the action first.
pgBrowser.Events.trigger(
'pgadmin:server:connection:lost', this.args.item, this.resp
);
}.bind(ctx);
$.ajax({
url: server.generate_url(
null, 'connect', args.info.server, true, args.info
),
dataType: 'json',
})
.done(function(res) {
if (res.success && 'connected' in res.data) {
if (res.data.connected) {
// Server is connected, but - the connection with the
// particular database has been lost.
pgBrowser.Events.trigger(
'pgadmin:database:connection:lost', args.item, jsonResp
);
return;
}
}
// Server was not connected, we should first try to connect
// the server.
reconnectServer();
})
.fail(function() {
reconnectServer();
});
return true;
} else if (jsonResp && jsonResp.info == 'CRYPTKEY_MISSING' && xhr.status == 503) {
/* Suppress the error here and handle in pgNotifier wherever
* required, as it has callback option
*/
return false;
}
return false;
}

View File

@@ -87,13 +87,6 @@
}
}
}
.alertify_tools_dialog_properties .pg-prop-status-bar {
position: absolute;
right: 0;
left: 0;
bottom: 0;
z-index: 1;
}
.error-in-grid {
border-radius: $border-radius !important;

View File

@@ -1,303 +0,0 @@
/* Overrides alertify js headers */
.alertify {
z-index: 3000;
position: fixed;
.ajs-header {
padding: 6px 10px !important;
//margin is calculated with -$alertify-borderremove-margin, adjust the header
min-height: $title-height + $alertify-borderremove-margin !important;
max-height: $title-height + $alertify-borderremove-margin !important;
background-color: $alert-header-bg;
font-size: $font-size-base;
font-weight: bold;
color: $alert-header-fg;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
border-radius: 0rem;
border-top-left-radius: $panel-border-radius;
border-top-right-radius: $panel-border-radius;
border-bottom: none;
margin: -24px - $alertify-borderremove-margin; //-24px is default by alertify
margin-bottom: 0px;
&:hover {
background-color: $alert-header-bg;
}
}
.ajs-body {
background-color: $alert-dialog-body-bg !important;
color: $color-fg !important;
}
&.ajs-resizable,
&.ajs-maximized {
& .ajs-body {
& .ajs-content {
top: $title-height;
}
}
& .ajs-header{
//default is 0, to override the borders
margin: -$alertify-borderremove-margin;
}
& .ajs-handle {
z-index: 1020;
}
}
&.ajs-frameless {
& .ajs-body {
& .ajs-content {
top: 0 !important;
bottom: 0px !important;
padding: 0px;
}
}
}
&:not(.ajs-frameless) .ajs-body .ajs-content {
top: $title-height !important;
}
.ajs-body .ajs-content {
bottom: $footer-height-calc !important;
}
.ajs-wrap-text {
word-break: normal;
word-wrap: break-word;
}
/* Removes padding from alertify footer */
.ajs-footer {
padding: 0;
min-height: $footer-min-height;
border-top: $panel-border;
background-color: $color-bg !important;
color: $color-fg !important;
& .ajs-buttons {
border: none;
border-radius: 0rem;
border-bottom-left-radius: $panel-border-radius;
border-bottom-right-radius: $panel-border-radius;
padding: $footer-padding;
&.ajs-auxiliary .ajs-button,
&.ajs-primary .ajs-button {
margin: 0px 2px;
}
& .ajs-button {
font-family: $font-family-primary;
font-size: $font-size-base;
-webkit-font-smoothing: auto;
min-width: 0;
min-height: 0;
}
}
}
.ajs-commands {
margin: -22px 4px 0 0;
}
/* Replaces alertify button icons */
.ajs-commands button {
margin-left: 5px;
}
/* Prevent text blur in the runtime */
.ajs-dimmer,
.ajs-modal {
-webkit-transform: none;
}
.ajs-commands button.ajs-maximize {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAZklEQVQ4jcWTuw2AMAxEn5jBs7B/e0gpmAiKEGRS5QDBSS7v+Q8fSsCWQgDTA+DsGgJYuypumTNkWCWZg9q/HIAOSDim/xTUcu0exXXaxQG0teRVWQPLx2Gbe8B55yNqv7C4GV/TDq//J11odoZgAAAAAElFTkSuQmCC);
background-size: 14px;
}
.ajs-commands button.ajs-close {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAdklEQVQ4jd2SwQnAIAxF36GH0pOTFHEgF3IkR5LO0F4SCGJVEHroAy/f/E+igV+yAa6hO7nrcgAZuIBg9CBalppXEnDL0RA1q556ASdQqhBrLlLTxVch1uxHZiU2AuKs2Vdt23GGHSy/wfIvzOzBPhpjaRO/5wG/szevJ+ZXzAAAAABJRU5ErkJggg==);
}
/* Restyling alertify dialogue panel boundaries */
.ajs-dialog {
border: $panel-border;
border-radius: $panel-border-radius;
box-shadow: $dialog-box-shadow;
background-color: $alert-dialog-body-bg !important;
color: $color-fg !important;
}
.ajs-content {
padding-left: 0 !important;
padding-right: 0 !important;
}
}
.alertify.ajs-maximized .ajs-commands,
.alertify.ajs-resizable .ajs-commands {
margin: 2px 0px 0 0;
}
.ajs-commands {
position: absolute;
width: auto !important;
}
.ajs-pin, .ajs-maximize, .ajs-close {
width: 20px;
height: 20px;
border: $input-btn-border-width solid $btn-secondary-border !important;
background-color: $alert-action-bg !important;
font-size: 12px;
border-radius: $btn-border-radius;
position: relative;
cursor: pointer;
text-align: center;
overflow: hidden;
z-index: 1;
}
.ajs-pin:hover, .ajs-maximize:hover, .ajs-close:hover {
background-color: $alert-action-hover-bg !important;
}
.alertify.ajs-modeless.ajs-pinnable .ajs-commands button.ajs-pin {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAkElEQVQ4jWNkwAR8DAwMBxkYGMTQxF8xMDDYMzAwfMKiBwMYMDAw3GRgYPgPxTehYiSBKCQDonApYiLV1KFjABsDA4MpEt8UKkYUkGBgYDjPgAhAGD4PlSPooqNYNMPwUXRXM+IwBAbaoXQlktg/ZMUsWAxAVvASmyZCBiCDNwTkCRrwasANIOgFQoADinECAAtnIEoWoODLAAAAAElFTkSuQmCC);
background-size: 13px;
}
.alertify.ajs-maximized .ajs-commands button.ajs-maximize {
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAA8klEQVQ4jZ3QMUpDQRCH8V+ewULQE4iERTyCrQiDCpbaCKKljbV4A89gqVgGrCMDWlpaWwVPoFYiIjYv8hBJXjLN7s7u9+3wZ4aKiOWI2IJOi8dHuM7MXxj3WMHe3CRBKeUGvVJKllJG8CrmoNty6jMsYKeGoY/jtgI4bez7OMjMr2oKwaieRzDMIljDRUSgXQZPeG2cv7GOffQ7ETGPcyw2HozWQWY+jLN3M/MzIu4wwNKf+zeMFVSQmY/YbfzeuiqIiAonZgi1quErHNa9F7xPM8FlAx5iA9ttJRVu8VHDm5k5rDNpLRERWxHR+6c/MZMfLIJDwzY66IkAAAAASUVORK5CYII=);
}
/* Restyling alertify query results messages */
.alertify-notifier.ajs-right {
min-width: 250px;
width: auto;
width: initial;
max-width: 800px;
}
.alertify-notifier.ajs-right .ajs-message.ajs-visible {
padding: 0;
right: 0;
width: auto;
width: initial;
}
.alertify-notifier .ajs-message {
border-radius: $card-border-radius;
width: 100%;
}
.pg-alertify-button:before {
font-size: $font-size-base;
@at-root .ajs-button#{&} {
font-family: $font-family-icon;
margin-right: 5px;
font-weight: 900;
}
}
.pg-alertify-icon-button {
&:before {
line-height: 1.2;
font-family: $font-family-icon;
font-weight: 900;
}
}
.ajs-text-smoothing {
text-shadow: none;
-webkit-font-smoothing: antialiased;
}
.ajs-message.ajs-error.ajs-visible {
background: $alert-danger-bg;
border: $border-width solid $alert-danger-color;
color: $alert-danger-color;
@extend .ajs-text-smoothing;
}
.ajs-message.ajs-success.ajs-visible {
background: $alert-success-bg;
border: $border-width solid $alert-success-color;
color: $alert-success-color;
@extend .ajs-text-smoothing;
}
.ajs-message.ajs-warning.ajs-visible {
background: $alert-warning-bg;
border: $border-width solid $alert-warning-color;
color: $alert-warning-color;
@extend .ajs-text-smoothing;
}
.ajs-message.ajs-visible {
background: $alert-primary-bg;
border: $border-width solid $alert-primary-color;
color: $alert-primary-color;
@extend .ajs-text-smoothing;
}
.ajs-message > .media > .media-body.media-middle {
display: flex;
}
.alertify .ajs-dimmer {
background-color: $loading-bg;
}
/* It sometimes is applied to dialog and blocks the dialog from editing */
.alertify .ajs-dialog.ajs-capture:before {
display: none;
}
.alertify-no-animation {
.alertify .ajs-dimmer,
.alertify .ajs-modal,
.alertify-notifier,
.alertify-notifier .ajs-message.ajs-visible,
.alertify-notifier .ajs-message,
.alertify-notifier.ajs-center .ajs-message.ajs-visible,
.alertify-notifier.ajs-center .ajs-message
{
-moz-transition: none;
-webkit-transition: none;
-o-transition: none;
transition: none;
-webkit-transform: none;
transform: none;
}
.alertify.ajs-zoom.ajs-in:not(.ajs-hidden) .ajs-dialog {
-webkit-animation-name: ajs-noanimate;
animation-name: ajs-noanimate;
}
.alertify.ajs-zoom.ajs-out.ajs-hidden .ajs-dialog {
-webkit-animation-name: ajs-noanimate;
animation-name: ajs-noanimate;
}
@-webkit-keyframes ajs-noanimate {
-webkit-transform: none;
transform: none;
}
@keyframes ajs-noanimate {
-webkit-transform: none;
transform: none;
}
}
.alert-text-body {
color: $alert-color-fg;
}
.ajs-commands, .ajs-close {
button {
@extend .btn-secondary;
outline: none !important;
}
}

View File

@@ -130,15 +130,6 @@
.opacity-5 {
opacity: 0.5; }
.alertify .ajs-header,
.alertify .ajs-body {
font-family: $font-family-primary;
}
.alertify .ajs-body {
min-height: $footer-height-calc*1.5;
}
.pg-navbar {
font-size: $navbar-font-size;
background-color: $navbar-bg;

View File

@@ -25,7 +25,6 @@ $theme-colors: (
@import 'select2.overrides';
@import 'codemirror.overrides';
@import 'alert';
@import 'alertify.overrides';
@import 'backform.overrides';
@import 'pgadmin.grid';
@import 'pgadmin.style';

View File

@@ -274,7 +274,6 @@ $alert-header-bg: $color-primary !default;
$alert-header-fg: $white !default;
$alert-action-bg: $color-secondary !default;
$alert-action-hover-bg: $color-gray-light !default;
$alertify-borderremove-margin: $panel-border-width;
$alert-color-fg: $color-fg !default;
$alert-dialog-body-bg: $color-bg !default;