Remove usage of jQuery in pgAdmin.

Remove usage of Bootstrap in React components. #5701
This commit is contained in:
Aditya Toshniwal 2023-02-10 10:28:39 +05:30 committed by GitHub
parent 1806866bf5
commit 713ddb5f62
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
75 changed files with 1387 additions and 3477 deletions

View File

@ -58,7 +58,6 @@
"karma-webpack": "^5.0.0",
"loader-utils": "^3.2.1",
"mini-css-extract-plugin": "^1.3.5",
"popper.js": "^1.16.1",
"postcss-loader": "^5.0.0",
"process": "^0.11.10",
"prop-types": "^15.7.2",
@ -103,8 +102,6 @@
"babelify": "~10.0.0",
"bignumber.js": "^9.0.1",
"bootstrap": "^4.3.1",
"bootstrap-datepicker": "^1.8.0",
"bootstrap4-toggle": "^3.6.1",
"brace": "^0.11.1",
"browserfs": "^1.4.3",
"chart.js": "^3.0.0",
@ -122,6 +119,7 @@
"insert-if": "^1.1.0",
"ip-address": "^7.1.0",
"jquery": "^3.6.0",
"jquery-contextmenu": "^2.9.2",
"json-bignumber": "^1.0.1",
"jsoneditor": "^9.5.4",
"jsoneditor-react": "^3.1.1",
@ -137,6 +135,7 @@
"path-fx": "^2.0.0",
"pathfinding": "^0.4.18",
"paths-js": "^0.4.9",
"popper.js": "^1.16.1",
"postcss": "^8.2.15",
"raf": "^3.4.1",
"rc-dock": "^3.2.9",
@ -158,17 +157,15 @@
"react-timer-hook": "^3.0.5",
"react-virtualized-auto-sizer": "^1.0.6",
"react-window": "^1.8.5",
"select2": "^4.0.13",
"snapsvg-cjs": "^0.0.6",
"socket.io-client": "^4.5.0",
"split.js": "^1.5.10",
"styled-components": "^5.2.1",
"tempusdominus-bootstrap-4": "^5.1.2",
"tempusdominus-core": "^5.19.3",
"uplot": "^1.6.24",
"uplot-react": "^1.1.4",
"valid-filename": "^2.0.1",
"webcabin-docker": "git+https://github.com/pgadmin-org/wcdocker/#3df8aac825ee2892f4d824de273b779cc6dbcad8",
"webcabin-docker": "git+https://github.com/pgadmin-org/wcdocker/#460fc6d90ba170bb177faaa8277f5fbb8279522a",
"wkx": "^0.5.0",
"xterm": "^4.11.0",
"xterm-addon-fit": "^0.5.0",

View File

@ -58,7 +58,7 @@ export default function AboutComponent() {
return (
<Box className={classes.container} ref={containerRef}>
<Grid container spacing={0}>
<Grid container spacing={0} style={{marginBottom: '8px'}}>
<Grid item lg={3} md={3} sm={3} xs={12}>
<InputLabel style={{fontWeight: 'bold'}}>{gettext('Version')}</InputLabel>
</Grid>
@ -66,7 +66,7 @@ export default function AboutComponent() {
<InputLabel>{aboutData.version}</InputLabel>
</Grid>
</Grid>
<Grid container spacing={0}>
<Grid container spacing={0} style={{marginBottom: '8px'}}>
<Grid item lg={3} md={3} sm={3} xs={12}>
<InputLabel style={{fontWeight: 'bold'}}>{gettext('Application Mode')}</InputLabel>
</Grid>
@ -74,7 +74,7 @@ export default function AboutComponent() {
<InputLabel>{aboutData.app_mode}</InputLabel>
</Grid>
</Grid>
<Grid container spacing={0}>
<Grid container spacing={0} style={{marginBottom: '8px'}}>
<Grid item lg={3} md={3} sm={3} xs={12}>
<InputLabel style={{fontWeight: 'bold'}}>{gettext('Current User')}</InputLabel>
</Grid>
@ -83,7 +83,7 @@ export default function AboutComponent() {
</Grid>
</Grid>
{ aboutData.nwjs &&
<Grid container spacing={0}>
<Grid container spacing={0} style={{marginBottom: '8px'}}>
<Grid item lg={3} md={3} sm={3} xs={12}>
<InputLabel style={{fontWeight: 'bold'}}>{gettext('NW.js Version')}</InputLabel>
</Grid>
@ -92,7 +92,7 @@ export default function AboutComponent() {
</Grid>
</Grid>
}
<Grid container spacing={0}>
<Grid container spacing={0} style={{marginBottom: '8px'}}>
<Grid item lg={3} md={3} sm={3} xs={12}>
<InputLabel style={{fontWeight: 'bold'}}>{gettext('Browser')}</InputLabel>
</Grid>
@ -100,7 +100,7 @@ export default function AboutComponent() {
<InputLabel>{aboutData.browser_details}</InputLabel>
</Grid>
</Grid>
<Grid container spacing={0}>
<Grid container spacing={0} style={{marginBottom: '8px'}}>
<Grid item lg={3} md={3} sm={3} xs={12}>
<InputLabel style={{fontWeight: 'bold'}}>{gettext('Operating System')}</InputLabel>
</Grid>
@ -108,7 +108,7 @@ export default function AboutComponent() {
<InputLabel>{aboutData.os_details}</InputLabel>
</Grid>
</Grid>
<Grid container spacing={0}>
<Grid container spacing={0} style={{marginBottom: '8px'}}>
<Grid item lg={3} md={3} sm={3} xs={12}>
<InputLabel style={{fontWeight: 'bold'}}>{gettext('pgAdmin Database File')}</InputLabel>
</Grid>
@ -116,7 +116,7 @@ export default function AboutComponent() {
<InputLabel>{aboutData.config_db}</InputLabel>
</Grid>
</Grid>
<Grid container spacing={0}>
<Grid container spacing={0} style={{marginBottom: '8px'}}>
<Grid item lg={3} md={3} sm={3} xs={12}>
<InputLabel style={{fontWeight: 'bold'}}>{gettext('Log File')}</InputLabel>
</Grid>

View File

@ -66,7 +66,6 @@ except ImportError as e:
MODULE_NAME = 'browser'
BROWSER_STATIC = 'browser.static'
JQUERY_ACIPLUGIN = 'jquery.aciplugin'
BROWSER_INDEX = 'browser.index'
PGADMIN_BROWSER = 'pgAdmin.Browser'
PASS_ERROR_MSG = gettext('Your password has not been changed.')

View File

@ -12,9 +12,9 @@ import { getNodePrivilegeRoleSchema } from '../../../../static/js/privilege.ui';
import { getNodeListByName } from '../../../../../../static/js/node_ajax';
define('pgadmin.node.schema', [
'sources/gettext', 'sources/url_for', 'jquery',
'sources/gettext', 'sources/url_for',
'pgadmin.browser', 'pgadmin.browser.collection',
], function(gettext, url_for, $, pgBrowser) {
], function(gettext, url_for, pgBrowser) {
// Extend the browser's collection class for schema collection
if (!pgBrowser.Nodes['coll-schema']) {

View File

@ -10,14 +10,15 @@
import { getNodeListByName } from '../../../../../../../../static/js/node_ajax';
import CompoundTriggerSchema from './compound_trigger.ui';
import Notify from '../../../../../../../../../static/js/helpers/Notifier';
import getApiInstance from '../../../../../../../../../static/js/api_instance';
define('pgadmin.node.compound_trigger', [
'sources/gettext', 'sources/url_for', 'jquery',
'sources/gettext', 'sources/url_for',
'sources/pgadmin', 'pgadmin.browser',
'pgadmin.node.schema.dir/schema_child_tree_node',
'pgadmin.browser.collection',
], function(
gettext, url_for, $, pgAdmin, pgBrowser, SchemaChildTreeNode
gettext, url_for, pgAdmin, pgBrowser, SchemaChildTreeNode
) {
if (!pgBrowser.Nodes['coll-compound_trigger']) {
@ -112,31 +113,27 @@ define('pgadmin.node.compound_trigger', [
return false;
let data = d;
$.ajax({
url: obj.generate_url(i, 'enable' , d, true),
type:'PUT',
data: {'is_enable_trigger' : 'O'},
dataType: 'json',
})
.done(function(res) {
if (res.success == 1) {
Notify.success(res.info);
t.removeIcon(i);
data.icon = 'icon-compound_trigger';
t.addIcon(i, {icon: data.icon});
t.unload(i);
t.setInode(false);
t.deselect(i);
// Fetch updated data from server
setTimeout(function() {
t.select(i);
}, 10);
}
})
.fail(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error);
getApiInstance().put(
obj.generate_url(i, 'enable' , d, true),
{'is_enable_trigger' : 'O'}
).then(({data: res})=> {
if(res.success == 1) {
Notify.success(res.info);
t.removeIcon(i);
data.icon = 'icon-compound_trigger';
t.addIcon(i, {icon: data.icon});
t.unload(i);
});
t.setInode(false);
t.deselect(i);
// Fetch updated data from server
setTimeout(function() {
t.select(i);
}, 10);
}
}).catch(function(error) {
Notify.pgRespErrorNotify(error);
t.unload(i);
});
},
/* Disable compound trigger */
disable_compound_trigger: function(args) {
@ -150,31 +147,27 @@ define('pgadmin.node.compound_trigger', [
return false;
let data = d;
$.ajax({
url: obj.generate_url(i, 'enable' , d, true),
type:'PUT',
data: {'is_enable_trigger' : 'D'},
dataType: 'json',
})
.done(function(res) {
if (res.success == 1) {
Notify.success(res.info);
t.removeIcon(i);
data.icon = 'icon-compound_trigger-bad';
t.addIcon(i, {icon: data.icon});
t.unload(i);
t.setInode(false);
t.deselect(i);
// Fetch updated data from server
setTimeout(function() {
t.select(i);
}, 10);
}
})
.fail(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error, gettext('Disable compound trigger failed'));
getApiInstance().put(
obj.generate_url(i, 'enable' , d, true),
{'is_enable_trigger' : 'D'}
).then(({data: res})=> {
if(res.success == 1) {
Notify.success(res.info);
t.removeIcon(i);
data.icon = 'icon-compound_trigger-bad';
t.addIcon(i, {icon: data.icon});
t.unload(i);
});
t.setInode(false);
t.deselect(i);
// Fetch updated data from server
setTimeout(function() {
t.select(i);
}, 10);
}
}).catch(function(error) {
Notify.pgRespErrorNotify(error);
t.unload(i);
});
},
},
canDrop: SchemaChildTreeNode.isTreeItemOfChildOfSchema,

View File

@ -10,13 +10,14 @@
import CheckConstraintSchema from './check_constraint.ui';
import Notify from '../../../../../../../../../../static/js/helpers/Notifier';
import _ from 'lodash';
import getApiInstance from '../../../../../../../../../../static/js/api_instance';
// Check Constraint Module: Node
define('pgadmin.node.check_constraint', [
'sources/gettext', 'sources/url_for', 'jquery',
'sources/gettext', 'sources/url_for',
'sources/pgadmin', 'pgadmin.browser',
'pgadmin.node.schema.dir/schema_child_tree_node', 'pgadmin.browser.collection',
], function(gettext, url_for, $, pgAdmin, pgBrowser, schemaChildTreeNode) {
], function(gettext, url_for, pgAdmin, pgBrowser, schemaChildTreeNode) {
// Check Constraint Node
if (!pgBrowser.Nodes['check_constraint']) {
@ -69,11 +70,8 @@ define('pgadmin.node.check_constraint', [
if (d) {
let data = d;
$.ajax({
url: obj.generate_url(i, 'validate', d, true),
type:'GET',
})
.done(function(res) {
getApiInstance().get(obj.generate_url(i, 'validate', d, true))
.then(({data: res})=>{
if (res.success == 1) {
Notify.success(res.info);
t.removeIcon(i);
@ -84,8 +82,8 @@ define('pgadmin.node.check_constraint', [
setTimeout(function() {t.select(i);}, 100);
}
})
.fail(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error);
.catch((error)=>{
Notify.pgRespErrorNotify(error);
t.unload(i);
});
}

View File

@ -10,12 +10,13 @@
import { getNodeForeignKeySchema } from './foreign_key.ui';
import Notify from '../../../../../../../../../../static/js/helpers/Notifier';
import _ from 'lodash';
import getApiInstance from '../../../../../../../../../../static/js/api_instance';
define('pgadmin.node.foreign_key', [
'sources/gettext', 'sources/url_for', 'jquery',
'sources/gettext', 'sources/url_for',
'sources/pgadmin', 'pgadmin.browser', 'pgadmin.browser.collection',
], function(
gettext, url_for, $, pgAdmin, pgBrowser
gettext, url_for, pgAdmin, pgBrowser
) {
// Extend the browser's node class for foreign key node
if (!pgBrowser.Nodes['foreign_key']) {
@ -65,11 +66,8 @@ define('pgadmin.node.foreign_key', [
if (d) {
let data = d;
$.ajax({
url: obj.generate_url(i, 'validate', d, true),
type:'GET',
})
.done(function(res) {
getApiInstance().get(obj.generate_url(i, 'validate', d, true))
.then(({data: res})=>{
if (res.success == 1) {
Notify.success(res.info);
t.removeIcon(i);
@ -80,8 +78,8 @@ define('pgadmin.node.foreign_key', [
setTimeout(function() {t.select(i);}, 100);
}
})
.fail(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error);
.catch((error)=>{
Notify.pgRespErrorNotify(error);
t.unload(i);
});
}

View File

@ -10,6 +10,7 @@
import { getNodePartitionTableSchema } from './partition.ui';
import Notify from '../../../../../../../../../static/js/helpers/Notifier';
import _ from 'lodash';
import getApiInstance from '../../../../../../../../../static/js/api_instance';
define([
'sources/gettext', 'sources/url_for', 'jquery',
@ -166,13 +167,8 @@ function(
if (!d)
return false;
$.ajax({
url: obj.generate_url(i, 'set_trigger' , d, true),
type:'PUT',
data: params,
dataType: 'json',
})
.done(function(res) {
getApiInstance().put(obj.generate_url(i, 'set_trigger' , d, true), params)
.then(({data: res})=>{
if (res.success == 1) {
Notify.success(res.info);
t.unload(i);
@ -183,8 +179,8 @@ function(
}, 10);
}
})
.fail(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error);
.catch((error)=>{
Notify.pgRespErrorNotify(error);
t.unload(i);
});
},
@ -213,17 +209,12 @@ function(
gettext('Are you sure you want to truncate table %s?', d.label),
function () {
let data = d;
$.ajax({
url: obj.generate_url(i, 'truncate' , d, true),
type:'PUT',
data: params,
dataType: 'json',
})
.done(function(res) {
getApiInstance().put(obj.generate_url(i, 'truncate' , d, true), params)
.then(({data: res})=>{
obj.on_done(res, data, t, i);
})
.fail(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error);
.catch((error)=>{
Notify.pgRespErrorNotify(error);
t.unload(i);
});
},
@ -244,15 +235,12 @@ function(
gettext('Are you sure you want to reset the statistics for table "%s"?', d._label),
function () {
let data = d;
$.ajax({
url: obj.generate_url(i, 'reset' , d, true),
type:'DELETE',
})
.done(function(res) {
getApiInstance().delete(obj.generate_url(i, 'reset' , d, true))
.then(({data: res})=>{
obj.on_done(res, data, t, i);
})
.fail(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error);
.catch((error)=>{
Notify.pgRespErrorNotify(error);
t.unload(i);
});
},
@ -273,11 +261,8 @@ function(
gettext('Detach Partition'),
gettext('Are you sure you want to detach the partition %s?', d._label),
function () {
$.ajax({
url: obj.generate_url(i, 'detach' , d, true),
type:'PUT',
})
.done(function(res) {
getApiInstance().put(obj.generate_url(i, 'detach' , d, true))
.then(({data: res})=>{
if (res.success == 1) {
Notify.success(res.info);
let n = t.next(i);
@ -293,8 +278,8 @@ function(
}
}
})
.fail(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error);
.catch((error)=>{
Notify.pgRespErrorNotify(error);
});
},
function() {/*This is intentional (SonarQube)*/}

View File

@ -9,6 +9,7 @@
import RuleSchema from './rule.ui';
import Notify from '../../../../../../../../../static/js/helpers/Notifier';
import _ from 'lodash';
import getApiInstance from '../../../../../../../../../static/js/api_instance';
define('pgadmin.node.rule', [
'sources/gettext', 'sources/url_for', 'jquery',
@ -134,13 +135,8 @@ define('pgadmin.node.rule', [
return false;
let data = d;
$.ajax({
url: obj.generate_url(i, 'obj' , d, true),
type:'PUT',
data: {'is_enable_rule' : 'O'},
dataType: 'json',
})
.done(function() {
getApiInstance().put(obj.generate_url(i, 'obj' , d, true), {'is_enable_rule' : 'O'})
.then(()=>{
Notify.success('Rule updated.');
t.removeIcon(i);
data.icon = 'icon-rule';
@ -153,9 +149,8 @@ define('pgadmin.node.rule', [
t.select(i);
}, 10);
})
.fail(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error);
t.unload(i);
.catch((error)=>{
Notify.pgRespErrorNotify(error);
});
},
/* Disable rule */
@ -170,13 +165,8 @@ define('pgadmin.node.rule', [
return false;
let data = d;
$.ajax({
url: obj.generate_url(i, 'obj' , d, true),
type:'PUT',
data: {'is_enable_rule' : 'D'},
dataType: 'json',
})
.done(function() {
getApiInstance().put(obj.generate_url(i, 'obj' , d, true), {'is_enable_rule' : 'D'})
.then(()=>{
Notify.success('Rule updated');
t.removeIcon(i);
data.icon = 'icon-rule-bad';
@ -189,9 +179,8 @@ define('pgadmin.node.rule', [
t.select(i);
}, 10);
})
.fail(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error, gettext('Disable rule failed'));
t.unload(i);
.catch((error)=>{
Notify.pgRespErrorNotify(error);
});
},
},

View File

@ -9,6 +9,7 @@
import { getNodeTableSchema } from './table.ui';
import Notify from '../../../../../../../../static/js/helpers/Notifier';
import _ from 'lodash';
import getApiInstance from '../../../../../../../../static/js/api_instance';
define('pgadmin.node.table', [
'pgadmin.tables.js/enable_disable_triggers',
@ -187,13 +188,8 @@ define('pgadmin.node.table', [
gettext('Are you sure you want to truncate table %s?', d.label),
function () {
let data = d;
$.ajax({
url: obj.generate_url(i, 'truncate' , d, true),
type:'PUT',
data: params,
dataType: 'json',
})
.done(function(res) {
getApiInstance().put(obj.generate_url(i, 'truncate' , d, true), params)
.then(({data: res})=>{
if (res.success == 1) {
Notify.success(res.info);
t.removeIcon(i);
@ -211,8 +207,8 @@ define('pgadmin.node.table', [
Notify.error(res.info);
}
})
.fail(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error);
.catch((error)=>{
Notify.pgRespErrorNotify(error);
t.unload(i);
});
}, function() {/*This is intentional (SonarQube)*/}
@ -233,11 +229,8 @@ define('pgadmin.node.table', [
gettext('Are you sure you want to reset the statistics for table "%s"?', d._label),
function () {
let data = d;
$.ajax({
url: obj.generate_url(i, 'reset' , d, true),
type:'DELETE',
})
.done(function(res) {
getApiInstance().delete(obj.generate_url(i, 'reset' , d, true))
.then(({data: res})=>{
if (res.success == 1) {
Notify.success(res.info);
t.removeIcon(i);
@ -252,8 +245,8 @@ define('pgadmin.node.table', [
}, 10);
}
})
.fail(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error);
.catch((error)=>{
Notify.pgRespErrorNotify(error);
t.unload(i);
});
},
@ -274,11 +267,8 @@ define('pgadmin.node.table', [
...d, _type: this.type,
};
// Fetch the total rows of a table
$.ajax({
url: obj.generate_url(i, 'count_rows' , newD, true),
type:'GET',
})
.done(function(res) {
getApiInstance().get(obj.generate_url(i, 'count_rows' , newD, true))
.then(({data: res})=>{
Notify.success(res.info, null);
d.rows_cnt = res.data.total_rows;
t.unload(i);
@ -288,8 +278,8 @@ define('pgadmin.node.table', [
t.select(i);
}, 10);
})
.fail(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error);
.catch((error)=>{
Notify.pgRespErrorNotify(error);
t.unload(i);
});
},

View File

@ -10,6 +10,7 @@ import { getNodeListByName, getNodeAjaxOptions } from '../../../../../../../../s
import TriggerSchema from './trigger.ui';
import Notify from '../../../../../../../../../static/js/helpers/Notifier';
import _ from 'lodash';
import getApiInstance from '../../../../../../../../../static/js/api_instance';
define('pgadmin.node.trigger', [
'sources/gettext', 'sources/url_for', 'jquery',
@ -108,13 +109,8 @@ define('pgadmin.node.trigger', [
return false;
let data = d;
$.ajax({
url: obj.generate_url(i, 'enable' , d, true),
type:'PUT',
data: {'is_enable_trigger' : 'O'},
dataType: 'json',
})
.done(function(res) {
getApiInstance().put(obj.generate_url(i, 'enable' , d, true), {'is_enable_trigger' : 'O'})
.then(({data: res})=>{
if (res.success == 1) {
Notify.success(res.info);
t.removeIcon(i);
@ -130,8 +126,8 @@ define('pgadmin.node.trigger', [
}, 10);
}
})
.fail(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error);
.catch((error)=>{
Notify.pgRespErrorNotify(error);
t.unload(i);
});
},
@ -147,13 +143,8 @@ define('pgadmin.node.trigger', [
return false;
let data = d;
$.ajax({
url: obj.generate_url(i, 'enable' , d, true),
type:'PUT',
data: {'is_enable_trigger' : 'D'},
dataType: 'json',
})
.done(function(res) {
getApiInstance().put(obj.generate_url(i, 'enable' , d, true), {'is_enable_trigger' : 'D'})
.then(({data: res})=>{
if (res.success == 1) {
Notify.success(res.info);
t.removeIcon(i);
@ -169,8 +160,8 @@ define('pgadmin.node.trigger', [
}, 10);
}
})
.fail(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error, gettext('Disable trigger failed'));
.catch((error)=>{
Notify.pgRespErrorNotify(error);
t.unload(i);
});
},

View File

@ -1965,8 +1965,8 @@ class BaseTableView(PGChildNodeView, BasePartitionTable, VacuumSettings):
request.data, encoding='utf-8'
)
# Convert str 'true' to boolean type
is_cascade = json.loads(data.get('cascade') or 'false')
is_identity = json.loads(data.get('identity') or 'false')
is_cascade = data.get('cascade') or False
is_identity = data.get('identity') or False
data = res['rows'][0]

View File

@ -2161,8 +2161,8 @@ class MViewNode(ViewNode, VacuumSettings):
request.data, encoding='utf-8'
)
is_concurrent = json.loads(data['concurrent'])
with_data = json.loads(data['with_data'])
is_concurrent = data['concurrent']
with_data = data['with_data']
data = dict()
data['is_concurrent'] = is_concurrent
data['is_with_data'] = with_data

View File

@ -13,6 +13,7 @@ import { getNodePrivilegeRoleSchema } from '../../../../../static/js/privilege.u
import { getNodeVacuumSettingsSchema } from '../../../../../static/js/vacuum.ui';
import Notify from '../../../../../../../../static/js/helpers/Notifier';
import _ from 'lodash';
import getApiInstance from '../../../../../../../../static/js/api_instance';
define('pgadmin.node.mview', [
'sources/gettext', 'sources/url_for', 'jquery',
@ -181,47 +182,41 @@ define('pgadmin.node.mview', [
return;
}
$.ajax({
url: obj.generate_url(i, 'check_utility_exists' , d, true),
type: 'GET',
dataType: 'json',
}).done(function(res) {
if (!res.success) {
const api = getApiInstance();
api.get(obj.generate_url(i, 'check_utility_exists' , d, true))
.then(({data: res})=>{
if (!res.success) {
Notify.alert(
gettext('Utility not found'),
res.errormsg
);
return;
}
api.put(obj.generate_url(i, 'refresh_data' , d, true), {'concurrent': args.concurrent, 'with_data': args.with_data})
.then(({data: refreshed_res})=>{
if (refreshed_res.data && refreshed_res.data.status) {
//Do nothing as we are creating the job and exiting from the main dialog
pgBrowser.BgProcessManager.startProcess(refreshed_res.data.job_id, refreshed_res.data.desc);
} else {
Notify.alert(
gettext('Failed to create materialized view refresh job.'),
refreshed_res.errormsg
);
}
})
.catch((error)=>{
Notify.pgRespErrorNotify(
error, gettext('Failed to create materialized view refresh job.')
);
});
})
.catch(()=>{
Notify.alert(
gettext('Utility not found'),
res.errormsg
gettext('Failed to fetch Utility information')
);
return;
}
// Make ajax call to refresh mview data
$.ajax({
url: obj.generate_url(i, 'refresh_data' , d, true),
type: 'PUT',
data: {'concurrent': args.concurrent, 'with_data': args.with_data},
dataType: 'json',
})
.done(function(refreshed_res) {
if (refreshed_res.data && refreshed_res.data.status) {
//Do nothing as we are creating the job and exiting from the main dialog
pgBrowser.BgProcessManager.startProcess(refreshed_res.data.job_id, refreshed_res.data.desc);
} else {
Notify.alert(
gettext('Failed to create materialized view refresh job.'),
refreshed_res.errormsg
);
}
})
.fail(function(xhr, status, error) {
Notify.pgRespErrorNotify(
xhr, error, gettext('Failed to create materialized view refresh job.')
);
});
}).fail(function() {
Notify.alert(
gettext('Utility not found'),
gettext('Failed to fetch Utility information')
);
});
});
},
is_version_supported: function(data, item) {

View File

@ -14,6 +14,7 @@ import DatabaseSchema from './database.ui';
import Notify from '../../../../../../static/js/helpers/Notifier';
import { showServerPassword } from '../../../../../../static/js/Dialogs/index';
import _ from 'lodash';
import getApiInstance, { parseApiError } from '../../../../../../static/js/api_instance';
define('pgadmin.node.database', [
'sources/gettext', 'sources/url_for', 'jquery',
@ -228,41 +229,38 @@ define('pgadmin.node.database', [
gettext('Are you sure you want to disconnect from database - %s?', d.label),
function() {
let data = d;
$.ajax({
url: obj.generate_url(i, 'connect', d, true),
type:'DELETE',
})
.done(function(res) {
if (res.success == 1) {
let prv_i = t.parent(i);
if(res.data.info_prefix) {
res.info = `${_.escape(res.data.info_prefix)} - ${res.info}`;
}
Notify.success(res.info);
t.removeIcon(i);
data.connected = false;
data.icon = data.isTemplate ? 'icon-database-template-not-connected':'icon-database-not-connected';
t.addIcon(i, {icon: data.icon});
t.unload(i);
pgBrowser.Events.trigger('pgadmin:browser:tree:update-tree-state', i);
setTimeout(function() {
t.select(prv_i);
}, 10);
} else {
try {
Notify.error(res.errormsg);
} catch (e) {
console.warn(e.stack || e);
}
t.unload(i);
getApiInstance().delete(
obj.generate_url(i, 'connect', d, true),
).then(({data: res})=> {
if (res.success == 1) {
let prv_i = t.parent(i);
if(res.data.info_prefix) {
res.info = `${_.escape(res.data.info_prefix)} - ${res.info}`;
}
})
.fail(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error);
Notify.success(res.info);
t.removeIcon(i);
data.connected = false;
data.icon = data.isTemplate ? 'icon-database-template-not-connected':'icon-database-not-connected';
t.addIcon(i, {icon: data.icon});
t.unload(i);
});
pgBrowser.Events.trigger('pgadmin:browser:tree:update-tree-state', i);
setTimeout(function() {
t.select(prv_i);
}, 10);
} else {
try {
Notify.error(res.errormsg);
} catch (e) {
console.warn(e.stack || e);
}
t.unload(i);
}
}).catch(function(error) {
Notify.pgRespErrorNotify(error);
t.unload(i);
});
},
function() { return true; }
);
@ -372,16 +370,17 @@ define('pgadmin.node.database', [
},
};
let api = getApiInstance();
let connect_to_database = function(obj, data, tree, item, _wasConnected) {
connect(obj, data, tree, item, _wasConnected);
},
connect = function (obj, data, tree, item, _wasConnected) {
let wasConnected = _wasConnected || data.connected,
onFailure = function(
xhr, status, error, _model, _data, _tree, _item, _status
error, _model, _data, _tree, _item, _status
) {
data.is_connecting = false;
if (xhr.status != 200 && xhr.responseText.search('Ticket expired') !== -1) {
if (error.response?.status != 200 && error.response?.request?.responseText?.search('Ticket expired') !== -1) {
tree.addIcon(_item, {icon: 'icon-server-connecting'});
let fetchTicket = Kerberos.fetch_ticket();
fetchTicket.then(
@ -392,7 +391,7 @@ define('pgadmin.node.database', [
tree.setInode(_item);
let dbIcon = data.isTemplate ? 'icon-database-template-not-connected':'icon-database-not-connected';
tree.addIcon(_item, {icon: dbIcon});
Notify.pgNotifier(fun_error, xhr, gettext('Connect to database.'));
Notify.pgNotifier(fun_error, error, gettext('Connect to database.'));
}
);
} else {
@ -402,7 +401,7 @@ define('pgadmin.node.database', [
tree.addIcon(_item, {icon: dbIcon});
}
Notify.pgNotifier('error', xhr, error, function(msg) {
Notify.pgNotifier('error', error, 'Error', function(msg) {
setTimeout(function() {
if (msg == 'CRYPTKEY_SET') {
connect_to_database(_model, _data, _tree, _item, _wasConnected);
@ -473,21 +472,21 @@ define('pgadmin.node.database', [
_tree.select(server);
};
$.post(
obj.generate_url(item, 'connect', data, true)
).done(function(res) {
if (res.success == 1) {
return onSuccess(res, obj, data, tree, item, wasConnected);
}
}).fail(function(xhr, status, error) {
if (xhr.status === 410) {
error = gettext('Error: Object not found - %s.', error);
}
api.post(obj.generate_url(item, 'connect', data, true))
.then(({data: res})=>{
if (res.success == 1) {
return onSuccess(res, obj, data, tree, item, wasConnected);
}
})
.catch((error)=>{
if (error.response?.status === 410) {
error = gettext('Error: Object not found - %s.', parseApiError(error));
}
return onFailure(
xhr, status, error, obj, data, tree, item, wasConnected
);
});
return onFailure(
error, obj, data, tree, item, wasConnected
);
});
};
}

View File

@ -11,6 +11,7 @@ import { getNodeAjaxOptions } from '../../../../../static/js/node_ajax';
import PgaJobSchema from './pga_job.ui';
import { getNodePgaJobStepSchema } from '../../steps/static/js/pga_jobstep.ui';
import Notify from '../../../../../../static/js/helpers/Notifier';
import getApiInstance from '../../../../../../static/js/api_instance';
define('pgadmin.node.pga_job', [
'sources/gettext', 'sources/url_for', 'jquery', 'pgadmin.browser',
@ -91,17 +92,15 @@ define('pgadmin.node.pga_job', [
d = i ? t.itemData(i) : undefined;
if (d) {
$.ajax({
url: obj.generate_url(i, 'run_now', d, true),
method:'PUT',
})
// 'pgagent.pga_job' table updated with current time to run the job
// now.
.done(function() { t.unload(i); })
.fail(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error);
t.unload(i);
});
getApiInstance().put(
obj.generate_url(i, 'run_now', d, true),
).then(({data: res})=> {
Notify.success(res.info);
t.unload(i);
}).catch(function(error) {
Notify.pgRespErrorNotify(error);
t.unload(i);
});
}
return false;

View File

@ -68,7 +68,7 @@ export default class BinaryPathSchema extends BaseUISchema {
Notify.alert(gettext('Validate binary path'), gettext(res.data.data));
})
.catch(function (error) {
Notify.pgNotifier(error, gettext('Failed to validate binary path.'));
Notify.pgNotifier('error', error, gettext('Failed to validate binary path.'));
});
}
return true;

View File

@ -12,6 +12,7 @@ import ServerSchema from './server.ui';
import Notify from '../../../../../static/js/helpers/Notifier';
import { showServerPassword, showChangeServerPassword, showNamedRestorePoint } from '../../../../../static/js/Dialogs/index';
import _ from 'lodash';
import getApiInstance, { parseApiError } from '../../../../../static/js/api_instance';
define('pgadmin.node.server', [
'sources/gettext', 'sources/url_for', 'jquery',
@ -196,45 +197,40 @@ define('pgadmin.node.server', [
notify = notify || _.isUndefined(notify) || _.isNull(notify);
let disconnect = function() {
$.ajax({
url: obj.generate_url(i, 'connect', d, true),
type:'DELETE',
})
.done(function(res) {
if (res.success == 1) {
Notify.success(res.info);
d = t.itemData(i);
t.removeIcon(i);
d.connected = false;
if (d.shared && pgAdmin.server_mode == 'True'){
d.icon = 'icon-shared-server-not-connected';
}else{
d.icon = 'icon-server-not-connected';
getApiInstance().delete(
obj.generate_url(i, 'connect', d, true),
).then(({data: res})=> {
if (res.success == 1) {
Notify.success(res.info);
d = t.itemData(i);
t.removeIcon(i);
d.connected = false;
if (d.shared && pgAdmin.server_mode == 'True'){
d.icon = 'icon-shared-server-not-connected';
}else{
d.icon = 'icon-server-not-connected';
}
t.addIcon(i, {icon: d.icon});
obj.callbacks.refresh.apply(obj, [null, i]);
setTimeout(() => {
t.close(i);
}, 10);
if (pgBrowser.serverInfo && d._id in pgBrowser.serverInfo) {
delete pgBrowser.serverInfo[d._id];
}
else {
try {
Notify.error(res.errormsg);
} catch (e) {
console.warn(e.stack || e);
}
t.addIcon(i, {icon: d.icon});
obj.callbacks.refresh.apply(obj, [null, i]);
setTimeout(() => {
t.close(i);
}, 10);
if (pgBrowser.serverInfo && d._id in pgBrowser.serverInfo) {
delete pgBrowser.serverInfo[d._id];
}
else {
try {
Notify.error(res.errormsg);
} catch (e) {
console.warn(e.stack || e);
}
t.unload(i);
}
pgBrowser.Events.trigger(
'pgadmin:server:disconnect', {item: i, data: d}, false
);
}})
.fail(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error);
t.unload(i);
});
t.unload(i);
}
}
}).catch(function(error) {
Notify.pgRespErrorNotify(error);
t.unload(i);
});
};
if (notify) {
@ -295,22 +291,19 @@ define('pgadmin.node.server', [
gettext('Reload server configuration'),
gettext('Are you sure you want to reload the server configuration on %s?', d.label),
function() {
$.ajax({
url: obj.generate_url(i, 'reload', d, true),
method:'GET',
})
.done(function(res) {
if (res.data.status) {
Notify.success(res.data.result);
}
else {
Notify.error(res.data.result);
}
})
.fail(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error);
t.unload(i);
});
getApiInstance().get(
obj.generate_url(i, 'reload', d, true),
).then(({data: res})=> {
if (res.data.status) {
Notify.success(res.data.result);
}
else {
Notify.error(res.data.result);
}
}).catch(function(error) {
Notify.pgRespErrorNotify(error);
t.unload(i);
});
},
function() { return true; },
);
@ -344,19 +337,16 @@ define('pgadmin.node.server', [
if (d) {
// Call to check if server is using pgpass file or not
$.ajax({
url: check_pgpass_url,
method:'GET',
})
.done(function(res) {
if (res.success && res.data.is_pgpass) {
is_pgpass_file_used = true;
}
showChangeServerPassword(gettext('Change Password'), d, obj, i, is_pgpass_file_used);
})
.fail(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error);
});
getApiInstance().get(
check_pgpass_url
).then(({data: res})=> {
if (res.success && res.data.is_pgpass) {
is_pgpass_file_used = true;
}
showChangeServerPassword(gettext('Change Password'), d, obj, i, is_pgpass_file_used);
}).catch(function(error) {
Notify.pgRespErrorNotify(error);
});
}
return false;
@ -387,18 +377,14 @@ define('pgadmin.node.server', [
if (!d)
return false;
$.ajax({
url: obj.generate_url(i, 'wal_replay' , d, true),
type:'DELETE',
dataType: 'json',
})
.done(function(res) {
obj.on_done(res, t, i);
})
.fail(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error);
t.unload(i);
});
getApiInstance().delete(
obj.generate_url(i, 'wal_replay' , d, true)
).then(({data: res})=> {
obj.on_done(res, t, i);
}).catch(function(error) {
Notify.pgRespErrorNotify(error);
t.unload(i);
});
},
/* Resume WAL Replay */
@ -412,18 +398,14 @@ define('pgadmin.node.server', [
if (!d)
return false;
$.ajax({
url: obj.generate_url(i, 'wal_replay' , d, true),
type:'PUT',
dataType: 'json',
})
.done(function(res) {
obj.on_done(res, t, i);
})
.fail(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error);
t.unload(i);
});
getApiInstance().put(
obj.generate_url(i, 'wal_replay' , d, true)
).then(({data: res})=> {
obj.on_done(res, t, i);
}).catch(function(error) {
Notify.pgRespErrorNotify(error);
t.unload(i);
});
},
/* Cleat saved database server password */
@ -439,22 +421,19 @@ define('pgadmin.node.server', [
gettext('Clear saved password'),
gettext('Are you sure you want to clear the saved password for server %s?', d.label),
function() {
$.ajax({
url: obj.generate_url(i, 'clear_saved_password', d, true),
method:'PUT',
})
.done(function(res) {
if (res.success == 1) {
Notify.success(res.info);
t.itemData(i).is_password_saved=res.data.is_password_saved;
}
else {
Notify.error(res.info);
}
})
.fail(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error);
});
getApiInstance().put(
obj.generate_url(i, 'clear_saved_password' , d, true)
).then(({data: res})=> {
if (res.success == 1) {
Notify.success(res.info);
t.itemData(i).is_password_saved=res.data.is_password_saved;
}
else {
Notify.error(res.info);
}
}).catch(function(error) {
Notify.pgRespErrorNotify(error);
});
},
function() { return true; }
);
@ -476,22 +455,19 @@ define('pgadmin.node.server', [
gettext('Clear SSH Tunnel password'),
gettext('Are you sure you want to clear the saved password of SSH Tunnel for server %s?', d.label),
function() {
$.ajax({
url: obj.generate_url(i, 'clear_sshtunnel_password', d, true),
method:'PUT',
})
.done(function(res) {
if (res.success == 1) {
Notify.success(res.info);
t.itemData(i).is_tunnel_password_saved=res.data.is_tunnel_password_saved;
}
else {
Notify.error(res.info);
}
})
.fail(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error);
});
getApiInstance().put(
obj.generate_url(i, 'clear_sshtunnel_password' , d, true)
).then(({data: res})=> {
if (res.success == 1) {
Notify.success(res.info);
t.itemData(i).is_tunnel_password_saved=res.data.is_tunnel_password_saved;
}
else {
Notify.error(res.info);
}
}).catch(function(error) {
Notify.pgRespErrorNotify(error);
});
},
function() { return true; }
);
@ -595,8 +571,8 @@ define('pgadmin.node.server', [
// Open properties dialog in edit mode
let server_url = obj.generate_url(item, 'obj', data, true);
// Fetch the updated data
$.get(server_url)
.done(function(res) {
getApiInstance().get(server_url)
.then(({data: res})=>{
if (res.shared && _.isNull(res.username) && data.user_id != current_user.id) {
if (!res.service) {
pgAdmin.Browser.Node.callbacks.show_obj_properties.call(
@ -617,13 +593,14 @@ define('pgadmin.node.server', [
else if (res.cloud_status == -1) {
pgAdmin.Browser.BgProcessManager.recheckCloudServer(data._id);
}
}).always(function(){
})
.then(()=>{
data.is_connecting = false;
});
let wasConnected = reconnect || data.connected,
onFailure = function(
xhr, status, error, _node, _data, _tree, _item, _wasConnected
xhr, error, _node, _data, _tree, _item, _wasConnected
) {
data.connected = false;
@ -647,7 +624,7 @@ define('pgadmin.node.server', [
},
function() {
tree.addIcon(_item, {icon: 'icon-server-not-connected'});
Notify.pgNotifier('Connection error', xhr, gettext('Connect to server.'));
Notify.pgNotifier('error', 'Connection error', xhr, gettext('Connect to server.'));
}
);
} else {
@ -750,20 +727,20 @@ define('pgadmin.node.server', [
tree.removeIcon(item);
tree.addIcon(item, {icon: 'icon-server-connecting'});
let url = obj.generate_url(item, 'connect', data, true);
$.post(url)
.done(function(res) {
getApiInstance().post(url)
.then(({data: res})=>{
if (res.success == 1) {
return onSuccess(
res, obj, data, tree, item, wasConnected
);
}
})
.fail(function(xhr, status, error) {
.catch((xhr)=>{
return onFailure(
xhr, status, error, obj, data, tree, item, wasConnected
xhr.response?.request, parseApiError(xhr), obj, data, tree, item, wasConnected
);
})
.always(function(){
.then(()=>{
data.is_connecting = false;
});
};
@ -773,8 +750,9 @@ define('pgadmin.node.server', [
tree.setLeaf(item);
tree.removeIcon(item);
tree.addIcon(item, {icon: 'icon-server-connecting'});
$.get(url)
.done(function(res) {
getApiInstance().get(url)
.then(({data: res})=>{
tree.setInode(item);
if (res && res.data) {
if (typeof res.data.icon == 'string') {
@ -796,14 +774,14 @@ define('pgadmin.node.server', [
);
}
})
.fail(function(xhr, status, error) {
.catch((error)=>{
tree.setInode(item);
if (data.shared && pgAdmin.server_mode == 'True'){
tree.addIcon(item, {icon: 'icon-shared-server-not-connected'});
}else{
tree.addIcon(item, {icon: 'icon-server-not-connected'});
}
Notify.pgRespErrorNotify(xhr, error);
Notify.pgRespErrorNotify(error);
});
};
}

View File

@ -16,23 +16,26 @@ import { checkMasterPassword } from '../../../static/js/Dialogs/index';
import { pgHandleItemError } from '../../../static/js/utils';
import { Search } from './quick_search/trigger_search';
import { send_heartbeat, stop_heartbeat } from './heartbeat';
import getApiInstance from '../../../static/js/api_instance';
define('pgadmin.browser', [
'sources/gettext', 'sources/url_for', 'require', 'jquery',
'bootstrap', 'sources/pgadmin', 'bundled_codemirror',
'sources/gettext', 'sources/url_for', 'jquery',
'sources/pgadmin', 'bundled_codemirror',
'sources/check_node_visibility', './toolbar', 'pgadmin.help',
'sources/csrf', 'sources/utils', 'sources/window', 'pgadmin.authenticate.kerberos',
'sources/tree/tree_init',
'pgadmin.browser.utils', 'wcdocker', 'jquery.contextmenu',
'pgadmin.browser.utils',
'pgadmin.browser.preferences', 'pgadmin.browser.messages',
'pgadmin.browser.panel', 'pgadmin.browser.layout',
'pgadmin.browser.error', 'pgadmin.browser.frame',
'pgadmin.browser.frame',
'pgadmin.browser.node', 'pgadmin.browser.collection', 'pgadmin.browser.activity',
'sources/codemirror/addon/fold/pgadmin-sqlfoldcode',
'pgadmin.browser.keyboard', 'sources/tree/pgadmin_tree_save_state'
'pgadmin.browser.keyboard', 'sources/tree/pgadmin_tree_save_state',
/* wcDocker dependencies */
'bootstrap', 'jquery-contextmenu', 'wcdocker',
], function(
gettext, url_for, require, $,
Bootstrap, pgAdmin, codemirror,
gettext, url_for, $,
pgAdmin, codemirror,
checkNodeVisibility, toolBar, help, csrfToken, pgadminUtils, pgWindow,
Kerberos, InitTree,
) {
@ -201,9 +204,9 @@ define('pgadmin.browser', [
icon: '',
limit: 1,
content: '<div id="tree" class="browser-tree"></div>',
onCreate: function(panel, $container) {
onCreate: function(panel, container) {
toolBar.initializeToolbar(panel, wcDocker);
$container.addClass('pg-no-overflow');
container.classList.add('pg-no-overflow');
},
}),
// Properties of the object node
@ -216,10 +219,10 @@ define('pgadmin.browser', [
isPrivate: true,
elContainer: true,
limit: 1,
content: '<div class="obj_properties container-fluid h-100"><div role="status" class="pg-panel-message">' + select_object_msg + '</div></div>',
content: '<div class="obj_properties"><div role="status" class="pg-panel-message">' + select_object_msg + '</div></div>',
events: panelEvents,
onCreate: function(myPanel, $container) {
$container.addClass('pg-no-overflow');
onCreate: function(myPanel, container) {
container.classList.add('pg-no-overflow');
},
}),
// Statistics of the object
@ -232,7 +235,7 @@ define('pgadmin.browser', [
isPrivate: false,
limit : 1,
canHide: true,
content: '<div class="negative-space p-2"><div role="status" class="pg-panel-message pg-panel-statistics-message">' + select_object_msg + '</div><div class="pg-panel-statistics-container d-none"></div></div>',
content: '<div></div>',
events: panelEvents,
}),
// Reversed engineered SQL for the object
@ -244,7 +247,7 @@ define('pgadmin.browser', [
isCloseable: false,
isPrivate: true,
limit: 1,
content: '<label for="sql-textarea" class="sr-only">' + gettext('SQL Code') + '</label><div class="sql_textarea"><textarea id="sql-textarea" name="sql-textarea" title="' + gettext('SQL Code') + '"></textarea></div>',
content: '<div></div>',
}),
// Dependencies of the object
'dependencies': new pgAdmin.Browser.Panel({
@ -256,7 +259,7 @@ define('pgadmin.browser', [
isPrivate: false,
canHide: true,
limit: 1,
content: '<div class="negative-space p-2"><div role="status" class="pg-panel-message pg-panel-depends-message">' + select_object_msg + '</div><div class="pg-panel-dependencies-container d-none"></div></div>',
content: '<div></div>',
events: panelEvents,
}),
// Dependents of the object
@ -269,7 +272,7 @@ define('pgadmin.browser', [
isPrivate: false,
limit: 1,
canHide: true,
content: '<div class="negative-space p-2"><div role="status" class="pg-panel-message pg-panel-depends-message">' + select_object_msg + '</div><div class="pg-panel-dependents-container d-none"></div></div>',
content: '<div></div>',
events: panelEvents,
}),
// Background processes
@ -282,7 +285,7 @@ define('pgadmin.browser', [
isPrivate: false,
limit: 1,
canHide: true,
content: '<div class="negative-space p-2"><div class="pg-panel-processes-container d-none"></div></div>',
content: '<div></div>',
events: panelEvents,
}),
},
@ -526,17 +529,6 @@ define('pgadmin.browser', [
initializeModalProvider();
initializeNotifier();
// Syntax highlight the SQL Pane
if(document.getElementById('sql-textarea')){
obj.editor = CodeMirror.fromTextArea(
document.getElementById('sql-textarea'), {
lineNumbers: true,
mode: 'text/x-pgsql',
readOnly: true,
extraKeys: pgAdmin.Browser.editor_shortcut_keys,
screenReaderLabel: gettext('SQL'),
});
}
/* Cache may take time to load for the first time
* Reflect the changes once cache is available
*/
@ -568,18 +560,15 @@ define('pgadmin.browser', [
// Register scripts and add menus
pgBrowser.utils.registerScripts(this);
let headers = {};
headers[pgAdmin.csrf_token_header] = pgAdmin.csrf_token;
// Ping the server every 5 minutes
setInterval(function() {
$.ajax({
url: url_for('misc.cleanup'),
type:'POST',
headers: headers,
})
.done(function() {/*This is intentional (SonarQube)*/})
.fail(function() {/*This is intentional (SonarQube)*/});
getApiInstance().post(
url_for('misc.cleanup')
).then(()=> {
/*This is intentional (SonarQube)*/
}).catch(function() {
/*This is intentional (SonarQube)*/
});
}, 300000);
obj.Events.on(
@ -608,12 +597,9 @@ define('pgadmin.browser', [
if (this.tree) this.tree.resizeTree();
},
check_corrupted_db_file: function() {
$.ajax({
url: url_for('browser.check_corrupted_db_file'),
type: 'GET',
dataType: 'json',
contentType: 'application/json',
}).done((res)=> {
getApiInstance().get(
url_for('browser.check_corrupted_db_file')
).then(({data: res})=> {
if(res.data.length > 0) {
Notify.alert(
@ -626,16 +612,14 @@ define('pgadmin.browser', [
res.data.substring(0, res.data.length - 14),
);
}
}).fail(function(xhr, status, error) {
}).catch(function(error) {
Notify.alert(error);
});
},
check_master_password: function(on_resp_callback) {
$.ajax({
url: url_for('browser.check_master_password'),
type: 'GET',
contentType: 'application/json',
}).done((res)=> {
getApiInstance().get(
url_for('browser.check_master_password')
).then(({data: res})=> {
if(on_resp_callback) {
if(res.data) {
on_resp_callback(true);
@ -643,23 +627,21 @@ define('pgadmin.browser', [
on_resp_callback(false);
}
}
}).fail(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error);
}).catch(function(error) {
Notify.pgRespErrorNotify(error);
});
},
reset_master_password: function() {
let self = this;
$.ajax({
url: url_for('browser.set_master_password'),
type: 'DELETE',
contentType: 'application/json',
}).done((res)=> {
getApiInstance().delete(
url_for('browser.set_master_password')
).then(({data: res})=> {
if(!res.data) {
self.set_master_password('');
}
}).fail(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error);
}).catch(function(error) {
Notify.pgRespErrorNotify(error);
});
},
@ -1687,59 +1669,51 @@ define('pgadmin.browser', [
});
return;
}
let api = getApiInstance();
let fetchNodeInfo = function(__i, __d, __n) {
let info = __n.getTreeNodeHierarchy(__i),
url = __n.generate_url(__i, 'nodes', __d, true);
$.ajax({
url: url,
type: 'GET',
cache: false,
dataType: 'json',
})
.done(function(res) {
api.get(
url
).then(({data: res})=> {
// Node information can come as result/data
let newData = res.result || res.data;
let newData = res.result || res.data;
newData._label = newData.label;
newData.label = _.escape(newData.label);
newData._label = newData.label;
newData.label = _.escape(newData.label);
ctx.t.setLabel(ctx.i, {label: newData.label});
ctx.t.addIcon(ctx.i, {icon: newData.icon});
ctx.t.setId(ctx.i, {id: newData.id});
if (newData.inode)
ctx.t.setInode(ctx.i, {inode: true});
ctx.t.setLabel(ctx.i, {label: newData.label});
ctx.t.addIcon(ctx.i, {icon: newData.icon});
ctx.t.setId(ctx.i, {id: newData.id});
if (newData.inode)
ctx.t.setInode(ctx.i, {inode: true});
// This will update the tree item data.
let itemData = ctx.t.itemData(ctx.i);
_.extend(itemData, newData);
// This will update the tree item data.
let itemData = ctx.t.itemData(ctx.i);
_.extend(itemData, newData);
if (
__n.can_expand && typeof(__n.can_expand) == 'function'
) {
if (!__n.can_expand(itemData)) {
ctx.t.unload(ctx.i);
return;
}
if (
__n.can_expand && typeof(__n.can_expand) == 'function'
) {
if (!__n.can_expand(itemData)) {
ctx.t.unload(ctx.i);
return;
}
ctx.b._refreshNode(ctx, ctx.branch);
let success = (ctx.o && ctx.o.success) || ctx.success;
if (success && typeof(success) == 'function') {
success();
}
})
.fail(function(xhr, error) {
if (!pgHandleItemError(
xhr, {item: __i, info: info}
)) {
let contentType = xhr.getResponseHeader('Content-Type'),
jsonResp = (
contentType &&
contentType.indexOf('application/json') == 0 &&
JSON.parse(xhr.responseText)
) || {};
if (xhr.status == 410 && jsonResp.success == 0) {
}
ctx.b._refreshNode(ctx, ctx.branch);
let success = (ctx.o && ctx.o.success) || ctx.success;
if (success && typeof(success) == 'function') {
success();
}
}).catch(function(error) {
if (!pgHandleItemError(
error, {item: __i, info: info}
)) {
if(error.response.headers['content-type'] == 'application/json') {
let jsonResp = error.response.data ?? {};
if(error.response.status == 410 && jsonResp.success == 0) {
let parent = ctx.t.parent(ctx.i);
ctx.t.remove(ctx.i, {
@ -1755,16 +1729,17 @@ define('pgadmin.browser', [
},
});
}
Notify.pgNotifier(error, xhr, gettext('Error retrieving details for the node.'), function (msg) {
if (msg == 'CRYPTKEY_SET') {
fetchNodeInfo(__i, __d, __n);
} else {
console.warn(arguments);
}
});
}
});
Notify.pgNotifier('error', error, gettext('Error retrieving details for the node.'), function (msg) {
if (msg == 'CRYPTKEY_SET') {
fetchNodeInfo(__i, __d, __n);
} else {
console.warn(arguments);
}
});
}
});
}.bind(this);
if (n && n.collection_node) {
@ -1935,6 +1910,7 @@ define('pgadmin.browser', [
},
addChildTreeNodes: function(_treeHierarchy, _node, _type, _arrayIds, _callback) {
let api = getApiInstance();
let module = _type in pgBrowser.Nodes && pgBrowser.Nodes[_type],
childTreeInfo = _arrayIds.length && _.extend(
{}, _.mapValues(_treeHierarchy, function(_val) {
@ -1961,20 +1937,17 @@ define('pgadmin.browser', [
_node = _node || arguments[1];
$.ajax({
url: childNodeUrl,
dataType: 'json',
})
.done(function(res) {
if (res.success) {
arrayChildNodeData.push(res.data);
}
fetchNodeInfo(_callback);
})
.fail(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error);
fetchNodeInfo(_callback);
});
api.get(
childNodeUrl
).then(({data: res})=> {
if (res.success) {
arrayChildNodeData.push(res.data);
}
fetchNodeInfo(_callback);
}).catch(function(error) {
Notify.pgRespErrorNotify(error);
fetchNodeInfo(_callback);
});
};

View File

@ -1,63 +0,0 @@
/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2023, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import Notify from '../../../static/js/helpers/Notifier';
import _ from 'lodash';
define(
['sources/gettext', 'sources/pgadmin'],
function(gettext, pgAdmin) {
pgAdmin.Browser = pgAdmin.Browser || {};
_.extend(pgAdmin.Browser, {
report_error: function(title, message, info, callback) {
title = _.escape(title);
message = _.escape(message);
info = _.escape(info);
let text ='<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">'
+ '<div class="panel panel-default">'
+ '<div class="panel-heading" role="tab" id="headingOne">'
+ '<h4 class="panel-title">'
+ '<a data-toggle="collapse" data-parent="#accordion" href="#collapseOne" aria-expanded="true" aria-controls="collapseOne">' + gettext('Error message') + '</a>'
+ '</h4>'
+ '</div>'
+ '<div id="collapseOne" class="panel-collapse collapse show" role="tabpanel" aria-labelledby="headingOne">'
+ '<div class="panel-body" style="overflow: auto;">' + message + '</div>'
+ '</div>'
+ '</div>';
if (info != null && info != '') {
text += '<div class="panel panel-default">'
+ '<div class="panel-heading" role="tab" id="headingTwo">'
+ '<h4 class="panel-title">'
+ '<a class="collapsed" data-toggle="collapse" data-parent="#accordion" href="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">' + gettext('Additional info') + '</a>'
+ '</h4>'
+ '</div>'
+ '<div id="collapseTwo" class="panel-collapse collapse" role="tabpanel" aria-labelledby="headingTwo">'
+ '<div class="panel-body" style="overflow: auto;">' + info + '</div>'
+ '</div>'
+ '</div>'
+ '</div>';
}
text += '</div>';
Notify.alert(
_.unescape(title),
text,
function() {
if(callback) {
callback();
}
}
);
},
});
return pgAdmin.Browser.report_error;
});

View File

@ -46,7 +46,6 @@ define([
isPrivate: that.isPrivate,
isLayoutMember: that.isLayoutMember,
onCreate: function(myPanel) {
$(myPanel).data('pgAdminName', that.name);
myPanel.initSize(that.width, that.height);
if (!(myPanel.showTitle??true))
@ -61,13 +60,17 @@ define([
myPanel.layout().addItem($frameArea);
that.panel = myPanel;
let frame = new wcIFrame($frameArea, myPanel);
$(myPanel).data('frameInitialized', false);
$(myPanel).data('embeddedFrame', frame);
myPanel.frameData = {
pgAdminName: that.name,
frameInitialized: false,
embeddedFrame: frame,
};
if (that.url != '' && that.url != 'about:blank') {
setTimeout(function() {
frame.openURL(that.url);
$(myPanel).data('frameInitialized', true);
myPanel.frameData.frameInitialized = true;
pgBrowser.Events.trigger(
'pgadmin-browser:frame:urlloaded:' + that.name, frame,
that.url, self
@ -75,7 +78,7 @@ define([
}, 50);
} else {
frame.openURL('about:blank');
$(myPanel).data('frameInitialized', true);
myPanel.frameData.frameInitialized = true;
pgBrowser.Events.trigger(
'pgadmin-browser:frame:urlloaded:' + that.name, frame,
that.url, self
@ -112,7 +115,7 @@ define([
}
},
eventFunc: function(eventName) {
let name = $(this).data('pgAdminName');
let name = this.frameData.pgAdminName;
try {
pgBrowser.Events.trigger('pgadmin-browser:frame', eventName, this, arguments);

View File

@ -9,13 +9,10 @@
import _ from 'lodash';
import pgAdmin from '../../../static/js/pgadmin';
import $ from 'jquery';
import Mousetrap from 'mousetrap';
import * as commonUtils from '../../../static/js/utils';
import dialogTabNavigator from '../../../static/js/dialog_tab_navigator';
import * as keyboardFunc from 'sources/keyboard_shortcuts';
import pgWindow from 'sources/window';
import gettext from 'sources/gettext';
import pgWindow from 'sources/window';
const pgBrowser = pgAdmin.Browser = pgAdmin.Browser || {};
@ -78,33 +75,6 @@ _.extend(pgBrowser.keyboardNavigation, {
_.each(self.shortcutMethods, (keyCombo, callback) => {
self._bindWithMousetrap(keyCombo.shortcuts, self[callback], keyCombo.bindElem);
});
/* Dropdown submenu was not working properly for up/down arrow keys.
* So up/down/right/left events for dropdown were removed from Mousetrap and were
* handled manually.
*/
const LEFT_KEY = 37,
UP_KEY = 38,
RIGHT_KEY = 39,
DOWN_KEY = 40;
$('.pg-navbar').on('keydown', (event)=> {
switch(event.keyCode) {
case LEFT_KEY:
self.bindMainMenuLeft(event);
break;
case UP_KEY:
self.bindMainMenuUpDown(event, 'up');
break;
case RIGHT_KEY:
self.bindMainMenuRight(event);
break;
case DOWN_KEY:
self.bindMainMenuUpDown(event, 'down');
break;
}
});
},
_bindWithMousetrap: function(shortcuts, callback, bindElem) {
const self = this;
@ -179,89 +149,10 @@ _.extend(pgBrowser.keyboardNavigation, {
}
}, 1000);
},
bindMainMenuLeft: function(event) {
if ($(event.target).hasClass('nav-link')) { // Menu items
let currNavMenu = $(event.target).closest('.nav-item');
keyboardFunc._stopEventPropagation(event);
currNavMenu = currNavMenu.prev('.nav-item');
// Skip hidden menus
while(currNavMenu.hasClass('d-none')) {
currNavMenu = currNavMenu.prev('.nav-item');
}
currNavMenu.find('.dropdown-toggle').first().dropdown('toggle');
} else if($(event.target).closest('.dropdown-menu').length > 0) {
let currLi = $(event.target).closest('li');
keyboardFunc._stopEventPropagation(event);
/*close submenu*/
let currMenu = currLi.closest('.dropdown-menu');
if(currMenu.closest('.dropdown-submenu').length > 0) {
currMenu.removeClass('show');
currMenu.closest('.dropdown-submenu').removeClass('dropdown-submenu-visible');
currLi = currMenu.closest('.dropdown-submenu');
currLi.find('.dropdown-item').trigger('focus');
}
}
},
bindMainMenuRight: function(event) {
if ($(event.target).hasClass('nav-link')) { // Menu items
let currNavMenu = $(event.target).closest('.nav-item');
keyboardFunc._stopEventPropagation(event);
currNavMenu = currNavMenu.next('.nav-item');
// Skip hidden menus
while(currNavMenu.hasClass('d-none')) {
currNavMenu = currNavMenu.next('.nav-item');
}
currNavMenu.find('.dropdown-toggle').first().dropdown('toggle');
} else if($(event.target).closest('.dropdown-menu').length > 0) {
let currLi = $(event.target).closest('li');
keyboardFunc._stopEventPropagation(event);
/*open submenu if any*/
if(currLi.hasClass('dropdown-submenu')){
currLi.addClass('dropdown-submenu-visible');
currLi.find('.dropdown-menu').addClass('show');
currLi.find('.dropdown-menu .dropdown-item').first().trigger('focus');
}
}
},
bindMainMenuUpDown: function(event, combo) {
// Handle Sub-menus
if($(event.target).closest('.dropdown-menu').length > 0) {
keyboardFunc._stopEventPropagation(event);
let currLi = $(event.target).closest('li');
/*close all the submenus on movement*/
let dropMenu = $(event.target).closest('.dropdown-menu');
dropMenu.find('.show').removeClass('show');
dropMenu.find('.dropdown-submenu').removeClass('dropdown-submenu-visible');
if(combo === 'up') {
currLi = currLi.prev();
}
else if(combo === 'down'){
currLi = currLi.next();
}
/*do not focus on divider and disabled */
while(currLi.hasClass('dropdown-divider')
|| currLi.find('.dropdown-item').first().hasClass('disabled')) {
if(combo === 'up') {
currLi = currLi.prev();
}
else if(combo === 'down'){
currLi = currLi.next();
}
}
currLi.find('.dropdown-item').trigger('focus');
}
},
bindLeftTree: function() {
const tree = this.getTreeDetails();
$('#tree').trigger('focus');
document.querySelector('[id="tree"]').focus();
tree.t.select(tree.i);
},
bindSubMenuQueryTool: function() {
@ -336,17 +227,6 @@ _.extend(pgBrowser.keyboardNavigation, {
// Call refresh object callback
pgAdmin.Browser.Node.callbacks.refresh.call(pgAdmin.Browser.Nodes[tree.t.itemData(tree.i)._type]);
},
bindContextMenu: function(event) {
const tree = this.getTreeDetails();
let _srcElement = event.srcElement || event.target;
const left = $(_srcElement).find('.aciTreeEntry').position().left + 70;
const top = $(_srcElement).find('.aciTreeEntry').position().top + 70;
tree.t.blur(tree.i);
$('#tree').trigger('blur');
// Call context menu and set position
tree.i.children().contextMenu({x: left, y: top});
},
bindDirectDebugging: function() {
const tree = this.getTreeDetails();
const type = tree.t.itemData(tree.i)._type;
@ -359,24 +239,6 @@ _.extend(pgBrowser.keyboardNavigation, {
pgAdmin.Tools.Debugger.get_function_information(pgAdmin.Browser.Nodes[type]);
}
},
bindDropMultipleObjects: function() {
let isPropertyPanelVisible = this.isPropertyPanelVisible();
if (isPropertyPanelVisible === true && $('button.delete_multiple').length > 0) {
$('button.delete_multiple').click();
}
},
bindDropCascadeMultipleObjects: function() {
let isPropertyPanelVisible = this.isPropertyPanelVisible();
if (isPropertyPanelVisible === true && $('button.delete_multiple_cascade').length > 0) {
$('button.delete_multiple_cascade').click();
}
},
bindAddGridRow: function() {
let subNode = $(document.activeElement).closest('.object.subnode');
if ($(subNode).length) {
$(subNode).find('.add').click();
}
},
isPropertyPanelVisible: function() {
let isPanelVisible = false;
_.each(pgAdmin.Browser.docker.findPanels(), (panel) => {
@ -396,12 +258,6 @@ _.extend(pgBrowser.keyboardNavigation, {
d: selectedTreeNodeData,
};
},
getDialogTabNavigator: function(dialogContainer) {
const backward_shortcut = pgWindow.pgAdmin.Browser.get_preference('browser', 'dialog_tab_backward').value;
const forward_shortcut = pgWindow.pgAdmin.Browser.get_preference('browser', 'dialog_tab_forward').value;
return new dialogTabNavigator.dialogTabNavigator(dialogContainer, backward_shortcut, forward_shortcut);
},
bindOpenQuickSearch: function() {
pgWindow.pgAdmin.Browser.all_menus_cache.help.mnu_quick_search_help.callback();
},

View File

@ -9,11 +9,11 @@
import pgAdmin from 'sources/pgadmin';
import url_for from 'sources/url_for';
import $ from 'jquery';
import gettext from 'sources/gettext';
import 'wcdocker';
import pgWindow from 'sources/window';
import Notify from '../../../static/js/helpers/Notifier';
import getApiInstance from '../../../static/js/api_instance';
const pgBrowser = pgAdmin.Browser = pgAdmin.Browser || {};
@ -50,11 +50,8 @@ _.extend(pgBrowser, {
if(docker) {
let layout = docker.save(),
settings = { setting: layout_id, value: layout };
$.ajax({
type: 'POST',
url: url_for('settings.store_bulk'),
data: settings,
});
getApiInstance().post(url_for('settings.store_bulk'), settings);
}
},
@ -143,17 +140,15 @@ _.extend(pgBrowser, {
save_lock_layout: function(op) {
let browser = pgWindow.pgAdmin.Browser;
$.ajax({
url: url_for('browser.lock_layout'),
method: 'PUT',
contentType: 'application/json',
data: JSON.stringify({
getApiInstance().put(
url_for('browser.lock_layout'),
JSON.stringify({
'value': op,
}),
}).done(function() {
})
).then(()=> {
browser.cache_preferences('browser');
}).fail(function(xhr, error) {
Notify.pgNotifier(error, xhr, gettext('Failed to save the lock layout setting.'));
}).catch(function(error) {
Notify.pgNotifier('error', error, gettext('Failed to save the lock layout setting.'));
});
},

View File

@ -10,13 +10,14 @@
import {getNodeView, removeNodeView} from './node_view';
import Notify from '../../../static/js/helpers/Notifier';
import _ from 'lodash';
import getApiInstance from '../../../static/js/api_instance';
define('pgadmin.browser.node', [
'sources/gettext', 'jquery', 'sources/pgadmin',
'sources/gettext', 'sources/pgadmin',
'sources/browser/generate_url', 'sources/utils',
'pgadmin.browser.utils', 'pgadmin.browser.events',
], function(
gettext, $, pgAdmin, generateUrl, commonUtils
gettext, pgAdmin, generateUrl, commonUtils
) {
let wcDocker = window.wcDocker;
@ -354,9 +355,9 @@ define('pgadmin.browser.node', [
isLayoutMember: false,
canMaximise: true,
elContainer: true,
content: '<div class="obj_properties container-fluid h-100"><div role="status" class="pg-panel-message">' + gettext('Please wait while we fetch information ...') + '</div></div>',
onCreate: function(myPanel, $container) {
$container.addClass('pg-no-overflow');
content: '<div class="obj_properties"></div>',
onCreate: function(myPanel, container) {
container.classList.add('pg-no-overflow');
},
events: events,
});
@ -379,9 +380,9 @@ define('pgadmin.browser.node', [
isLayoutMember: false,
canMaximise: true,
elContainer: true,
content: '<div class="obj_properties container-fluid h-100"><div role="status" class="pg-panel-message">' + gettext('Please wait while we fetch information about the node from the server...') + '</div></div>',
onCreate: function(myPanel, $container) {
$container.addClass('pg-no-overflow');
content: '<div class="obj_properties"></div>',
onCreate: function(myPanel, container) {
container.classList.add('pg-no-overflow');
},
events: events,
});
@ -688,45 +689,41 @@ define('pgadmin.browser.node', [
}
Notify.confirm(title, msg,
function() {
$.ajax({
url: obj.generate_url(i, input.url, d, true),
type: 'DELETE',
})
.done(function(res) {
if(res.success == 2){
Notify.error(res.info, null);
return;
getApiInstance().delete(
obj.generate_url(i, input.url, d, true),
).then(({data: res})=> {
if(res.success == 2){
Notify.error(res.info, null);
return;
}
if (res.success == 0) {
Notify.alert(res.errormsg, res.info);
} else {
// Remove the node from tree and set collection node as selected.
let selectNextNode = true;
if(obj.selectParentNodeOnDelete) {
let prv_i = t.parent(i);
setTimeout(function() {
t.select(prv_i);
}, 10);
selectNextNode = false;
}
if (res.success == 0) {
pgBrowser.report_error(res.errormsg, res.info);
} else {
// Remove the node from tree and set collection node as selected.
let selectNextNode = true;
if(obj.selectParentNodeOnDelete) {
let prv_i = t.parent(i);
setTimeout(function() {
t.select(prv_i);
}, 10);
selectNextNode = false;
}
pgBrowser.removeTreeNode(i, selectNextNode);
pgBrowser.removeTreeNode(i, selectNextNode);
}
return true;
}).catch(function(xhr) {
let errmsg = xhr.responseText;
/* Error from the server */
if (xhr.status == 417 || xhr.status == 410 || xhr.status == 500) {
try {
let data = JSON.parse(xhr.responseText);
errmsg = data.info || data.errormsg;
} catch (e) {
console.warn(e.stack || e);
}
return true;
})
.fail(function(jqx) {
let errmsg = jqx.responseText;
/* Error from the server */
if (jqx.status == 417 || jqx.status == 410 || jqx.status == 500) {
try {
let data = JSON.parse(jqx.responseText);
errmsg = data.info || data.errormsg;
} catch (e) {
console.warn(e.stack || e);
}
}
pgBrowser.report_error(
gettext('Error dropping/removing %s: "%s"', obj.label, objName), errmsg);
});
}
Notify.alert(gettext('Error dropping/removing %s: "%s"', obj.label, objName), errmsg);
});
}
);
},
@ -822,23 +819,27 @@ define('pgadmin.browser.node', [
fgcolor = serverData.icon.split(' ')[2] || '';
if (bgcolor) {
let dynamic_class = 'pga_server_' + serverData._id + '_bgcolor',
style_tag;
let dynamic_class = 'pga_server_' + serverData._id + '_bgcolor';
// Prepare dynamic style tag
style_tag = '<style id=' + dynamic_class + ' type=\'text/css\'> \n';
style_tag += '.' + dynamic_class + ' .file-label {';
style_tag += ' border-radius: 3px; margin-bottom: 2px;';
style_tag += ' background: ' + bgcolor + ' !important;} \n';
if (fgcolor) {
style_tag += '.' + dynamic_class + ' span.file-name {';
style_tag += ' color: ' + fgcolor + ' !important;} \n';
}
style_tag += '</style>';
const styleTag = document.createElement('style');
styleTag.setAttribute('id', dynamic_class);
styleTag.setAttribute('type', 'text/css');
styleTag.innerText = `
.${dynamic_class} .file-label {
border-radius: 3px;
margin-bottom: 2px;
background: ${bgcolor} !important;
}
${fgcolor ? `
.${dynamic_class} span.file-name {
color: ${fgcolor} !important;
}
`:''}
`;
// Prepare dynamic style tag using template
$('#' + dynamic_class).remove();
$(style_tag).appendTo('head');
document.querySelector(`style[id="${dynamic_class}"]`).remove();
document.head.appendChild(styleTag);
// Add dynamic class to the tree node.
pgBrowser.tree.addCssClass(item, dynamic_class);
}
@ -895,7 +896,6 @@ define('pgadmin.browser.node', [
t = pgBrowser.tree,
data = _item && t.itemData(_item);
$(pgBrowser.panels['properties'].panel).removeData('node-prop');
pgBrowser.Events.trigger(
'pgadmin:browser:tree:refresh', _item || pgBrowser.tree.selected(), {
success: function() {

View File

@ -63,25 +63,8 @@ export function getNodeView(nodeType, treeNodeInfo, actionType, itemNodeData, fo
} else if(err.message){
console.error('error msg', err.message);
}
if (err?.response?.data?.info == 'CRYPTKEY_MISSING') {
Notify.pgNotifier('error', err.request, 'The master password is not set', function(msg) {
setTimeout(function() {
if (msg == 'CRYPTKEY_SET') {
resolve(initData());
} else if (msg == 'CRYPTKEY_NOT_SET') {
reject(err);
}
}, 100);
});
} else if (err?.response?.data?.errormsg) {
Notify.alert(
gettext('Error'),
gettext(err.response.data.errormsg)
);
reject(err);
}
reject(err);
Notify.pgRespErrorNotify(err);
});
}
});

View File

@ -11,8 +11,8 @@ import { getPanelView } from './panel_view';
import _ from 'lodash';
define(
['sources/pgadmin', 'jquery', 'wcdocker'],
function(pgAdmin, $) {
['sources/pgadmin', 'wcdocker'],
function(pgAdmin) {
let pgBrowser = pgAdmin.Browser = pgAdmin.Browser || {},
wcDocker = window.wcDocker;
@ -52,7 +52,9 @@ define(
limit: that.limit,
isLayoutMember: that.isLayoutMember,
onCreate: function(myPanel) {
$(myPanel).data('pgAdminName', that.name);
myPanel.panelData = {
pgAdminName: that.name,
};
myPanel.initSize(that.width, that.height);
if (!that.showTitle)
@ -64,18 +66,18 @@ define(
myPanel.icon(that.icon);
}
let $container = $('<div>', {
'class': 'pg-panel-content',
}).append($(that.content));
let container = document.createElement('div');
container.setAttribute('class', 'pg-panel-content');
container.innerHTML = that.content;
// Add extra classes
if (!_.isNull('extraClasses')) {
$container.addClass(that.extraClasses);
container.classList.add(that.extraClasses);
}
myPanel.maximisable(!!that.canMaximise);
myPanel.closeable(!!that.isCloseable);
myPanel.layout().addItem($container);
myPanel.layout().addItem(container);
that.panel = myPanel;
if (that.events && _.isObject(that.events)) {
_.each(that.events, function(v, k) {
@ -99,21 +101,20 @@ define(
});
if (that.onCreate && _.isFunction(that.onCreate)) {
that.onCreate.apply(that, [myPanel, $container]);
that.onCreate.apply(that, [myPanel, container]);
}
// Prevent browser from opening the drag file.
// Using addEventListener to avoid conflict with jquery.drag
['dragover', 'drop'].forEach((eventName)=>{
$container[0].addEventListener(eventName, function(event) {
container.addEventListener(eventName, function(event) {
event.stopPropagation();
event.preventDefault();
});
});
if (that.elContainer) {
myPanel.pgElContainer = $container;
$container.addClass('pg-el-container');
myPanel.pgElContainer = container;
_.each([
wcDocker.EVENT.RESIZED, wcDocker.EVENT.ATTACHED,
wcDocker.EVENT.DETACHED, wcDocker.EVENT.VISIBILITY_CHANGED,
@ -126,7 +127,7 @@ define(
if (myPanel._type == 'dashboard' || myPanel._type == 'processes') {
getPanelView(
pgBrowser.tree,
$container[0],
container,
pgBrowser,
myPanel._type
);
@ -136,7 +137,7 @@ define(
pgBrowser.onPreferencesChange('dashboards', function() {
getPanelView(
pgBrowser.tree,
$container[0],
container,
pgBrowser,
myPanel._type
);
@ -146,7 +147,7 @@ define(
pgBrowser.onPreferencesChange('graphs', function() {
getPanelView(
pgBrowser.tree,
$container[0],
container,
pgBrowser,
myPanel._type
);
@ -162,7 +163,7 @@ define(
if(myPanel.isVisible() && myPanel._type !== 'properties') {
getPanelView(
pgBrowser.tree,
$container[0],
container,
pgBrowser,
myPanel._type
);
@ -174,7 +175,7 @@ define(
if(myPanel.isVisible() && myPanel._type !== 'properties') {
getPanelView(
pgBrowser.tree,
$container[0],
container,
pgBrowser,
myPanel._type
);
@ -186,7 +187,7 @@ define(
if(myPanel.isVisible() && myPanel._type !== 'properties') {
getPanelView(
pgBrowser.tree,
$container[0],
container,
pgBrowser,
myPanel._type
);
@ -197,7 +198,7 @@ define(
}
},
eventFunc: function(eventName) {
let name = $(this).data('pgAdminName');
let name = this.panelData.pgAdminName;
try {
pgBrowser.Events.trigger(
'pgadmin-browser:panel', eventName, this, arguments
@ -248,18 +249,16 @@ define(
elAttr = 'xl';
}
p.pgElContainer.attr('el', elAttr);
p.pgElContainer.setAttribute('el', elAttr);
},
100
);
}
},
handleVisibility: function(eventName) {
if (_.isNull(pgBrowser.tree)) return;
let selectedPanel = pgBrowser.docker.findPanels(this._type)[0];
let isPanelVisible = selectedPanel.isVisible();
let $container = selectedPanel
let container = selectedPanel
.layout()
.scene()
.find('.pg-panel-content');
@ -268,7 +267,7 @@ define(
if (eventName == 'panelVisibilityChanged') {
getPanelView(
pgBrowser.tree,
$container[0],
container[0],
pgBrowser,
this._type
);
@ -277,7 +276,7 @@ define(
if (eventName == 'panelClosed' && selectedPanel._type == 'dashboard') {
getPanelView(
pgBrowser.tree,
$container[0],
container[0],
pgBrowser,
this._type,
false

View File

@ -9,12 +9,10 @@
import pgAdmin from 'sources/pgadmin';
import url_for from 'sources/url_for';
import $ from 'jquery';
import pgWindow from 'sources/window';
import Notify from '../../../static/js/helpers/Notifier';
import { calcFontSize } from '../../../static/js/utils';
import { shortcutToString } from '../../../static/js/components/ShortcutTitle';
import gettext from 'sources/gettext';
import getApiInstance from '../../../static/js/api_instance';
const pgBrowser = pgAdmin.Browser = pgAdmin.Browser || {};
@ -78,16 +76,11 @@ _.extend(pgBrowser, {
// Get and cache the preferences
cache_preferences: function (modulesChanged) {
let self = this,
headers = {};
headers[pgAdmin.csrf_token_header] = pgAdmin.csrf_token;
let self = this;
setTimeout(function() {
$.ajax({
url: url_for('preferences.get_all'),
headers: headers,
})
.done(function(res) {
getApiInstance().get(url_for('preferences.get_all'))
.then(({data: res})=>{
self.preferences_cache = res;
self.preference_version(self.generate_preference_version());
@ -97,43 +90,30 @@ _.extend(pgBrowser, {
pgBrowser.browserTreeState.init();
/* Once the cache is loaded after changing the preferences,
* notify the modules of the change
*/
* notify the modules of the change
*/
if(modulesChanged) {
if(typeof modulesChanged === 'string'){
$.event.trigger('prefchange:'+modulesChanged);
pgBrowser.Events.trigger('prefchange:'+modulesChanged);
} else {
_.each(modulesChanged, (val, key)=> {
$.event.trigger('prefchange:'+key);
pgBrowser.Events.trigger('prefchange:'+key);
});
}
}
})
.fail(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error);
.catch(function(error) {
Notify.pgRespErrorNotify(error);
});
}, 500);
},
triggerPreferencesChange: function(moduleChanged) {
$.event.trigger('prefchange:'+moduleChanged);
pgBrowser.Events.trigger('prefchange:'+moduleChanged);
},
reflectPreferences: function(module) {
let obj = this;
if(module === 'sqleditor' || module === null || typeof module === 'undefined') {
let sqlEditPreferences = obj.get_preferences_for_module('sqleditor');
$(obj?.editor?.getWrapperElement()).css(
'font-size', calcFontSize(sqlEditPreferences.sql_font_size)
);
obj?.editor?.setOption('tabSize', sqlEditPreferences.tab_size);
obj?.editor?.setOption('lineWrapping', sqlEditPreferences.wrap_code);
obj?.editor?.setOption('autoCloseBrackets', sqlEditPreferences.insert_pair_brackets);
obj?.editor?.setOption('matchBrackets', sqlEditPreferences.brace_matching);
obj?.editor?.refresh();
}
//browser preference
if(module === 'browser') {
let browserPreferences = obj.get_preferences_for_module('browser');
@ -158,13 +138,7 @@ _.extend(pgBrowser, {
},
onPreferencesChange: function(module, eventHandler) {
let eventWindow = pgWindow;
if (window.location === window.parent?.location ) {
// The page is in a new tab
eventWindow = window;
}
$(eventWindow).on('prefchange:'+module, function(event) {
pgBrowser.Events.on('prefchange:'+module, function(event) {
eventHandler(event);
});
},

View File

@ -52,6 +52,10 @@ samp,
border-style: solid;
border-width: 1px;
font-size: 1.15em;
color: $color-fg !important;
border-color: $border-color !important;
background-color: $color-secondary;
}
.pg-toolbar-psql {

View File

@ -168,28 +168,6 @@ define('pgadmin.browser.utils',
],
},
{% endif %}
// load the module right now
load_module: function(name, path, c) {
let obj = this;
require([name],function(m) {
try {
// initialize the module (if 'init' function present).
if (m.init && typeof(m.init) == 'function')
m.init();
} catch (e) {
// Log this exception on console to understand the issue properly.
console.log(e);
obj.report_error(gettext('Error loading script - ') + path);
}
if (c)
c.loaded += 1;
}, function() {
// Log the arguments on console to understand the issue properly.
console.log(arguments);
obj.report_error(gettext('Error loading script - ') + path);
});
}
};
return pgBrowser;
});

View File

@ -16,7 +16,7 @@ import { makeStyles } from '@material-ui/core/styles';
import url_for from 'sources/url_for';
import Graphs from './Graphs';
import Notify from '../../../static/js/helpers/Notifier';
import { Box, Tab, Tabs } from '@material-ui/core';
import { Box, Card, CardContent, CardHeader, Tab, Tabs } from '@material-ui/core';
import { PgIconButton } from '../../../static/js/components/Buttons';
import CancelIcon from '@material-ui/icons/Cancel';
import StopSharpIcon from '@material-ui/icons/StopSharp';
@ -108,6 +108,28 @@ const useStyles = makeStyles((theme) => ({
height: '1.9rem',
width: '2.2rem',
...theme.mixins.panelBorder,
},
chartCard: {
border: '1px solid '+theme.otherVars.borderColor,
},
chartCardContent: {
padding: '0.25rem 0.5rem',
height: '165px',
display: 'flex',
},
chartLegend: {
marginLeft: 'auto',
'& > div': {
display: 'flex',
fontWeight: 'normal',
'& .legend-value': {
marginLeft: '4px',
'& .legend-label': {
marginLeft: '4px',
}
}
}
}
}));
@ -901,33 +923,27 @@ Dashboard.propTypes = {
};
export function ChartContainer(props) {
const classes = useStyles();
return (
<div
className="card dashboard-graph"
role="object-document"
tabIndex="0"
aria-labelledby={props.id}
>
<div className="card-header">
<div className="d-flex">
<div id={props.id}>{props.title}</div>
<div className="ml-auto my-auto legend">
<div className="d-flex">
{props.datasets?.map((datum, i)=>(
<div className="legend-value" key={i}>
<span style={{backgroundColor: datum.borderColor}}>&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span className="legend-label">{datum.label}</span>
</div>
))}
</div>
<Card className={classes.chartCard} elevation={0}>
<CardHeader title={<Box display="flex" justifyContent="space-between">
<div id={props.id}>{props.title}</div>
<div className={classes.chartLegend}>
<div className="d-flex">
{props.datasets?.map((datum, i)=>(
<div className="legend-value" key={i}>
<span style={{backgroundColor: datum.borderColor}}>&nbsp;&nbsp;&nbsp;&nbsp;</span>
<span className="legend-label">{datum.label}</span>
</div>
))}
</div>
</div>
</div>
<div className="card-body dashboard-graph-body">
{!props.errorMsg && !props.isTest && props.children}
<ChartError message={props.errorMsg} />
</div>
</div>
</Box>} />
<CardContent className={classes.chartCardContent}>
{!props.errorMsg ? props.children : <EmptyPanelMessage text={props.errorMsg}/>}
</CardContent>
</Card>
);
}
@ -939,35 +955,3 @@ ChartContainer.propTypes = {
errorMsg: PropTypes.string,
isTest: PropTypes.bool
};
export function ChartError(props) {
if (props.message === null) {
return <></>;
}
return (
<div className="pg-panel-error pg-panel-message" role="alert">
{props.message}
</div>
);
}
ChartError.propTypes = {
message: PropTypes.string,
};
export function DashboardRow({ children }) {
return <div className="row dashboard-row">{children}</div>;
}
DashboardRow.propTypes = {
children: PropTypes.node.isRequired,
};
export function DashboardRowCol({ breakpoint, parts, children }) {
return <div className={`col-${breakpoint}-${parts}`}>{children}</div>;
}
DashboardRowCol.propTypes = {
breakpoint: PropTypes.oneOf(['xs', 'sm', 'md', 'lg', 'xl']).isRequired,
parts: PropTypes.number.isRequired,
children: PropTypes.node.isRequired,
};

View File

@ -8,7 +8,7 @@
//////////////////////////////////////////////////////////////
import React, { useEffect, useRef, useState, useReducer, useMemo } from 'react';
import { DATA_POINT_SIZE } from 'sources/chartjs';
import {ChartContainer, DashboardRowCol, DashboardRow} from './Dashboard';
import {ChartContainer} from './Dashboard';
import url_for from 'sources/url_for';
import axios from 'axios';
import gettext from 'sources/gettext';
@ -16,6 +16,7 @@ import {getGCD, getEpoch} from 'sources/utils';
import {useInterval, usePrevious} from 'sources/custom_hooks';
import PropTypes from 'prop-types';
import StreamingChart from '../../../static/js/components/PgChart/StreamingChart';
import { Grid } from '@material-ui/core';
export const X_AXIS_LENGTH = 75;
@ -208,7 +209,7 @@ export default function Graphs({preferences, sid, did, pageVisible, enablePoll=t
return (
<>
<div data-testid='graph-poll-delay' className='d-none'>{pollDelay}</div>
<div data-testid='graph-poll-delay' style={{display: 'none'}}>{pollDelay}</div>
{chartDrawnOnce &&
<GraphsWrapper
sessionStats={transformData(sessionStats, preferences['session_stats_refresh'], preferences['use_diff_point_style'])}
@ -252,36 +253,36 @@ export function GraphsWrapper(props) {
return (
<>
<DashboardRow>
<DashboardRowCol breakpoint='md' parts={6}>
<Grid container spacing={1}>
<Grid item md={6}>
<ChartContainer id='sessions-graph' title={props.isDatabase ? gettext('Database sessions') : gettext('Server sessions')}
datasets={props.sessionStats.datasets} errorMsg={props.errorMsg} isTest={props.isTest}>
<StreamingChart data={props.sessionStats} dataPointSize={DATA_POINT_SIZE} xRange={X_AXIS_LENGTH} options={options} />
</ChartContainer>
</DashboardRowCol>
<DashboardRowCol breakpoint='md' parts={6}>
</Grid>
<Grid item md={6}>
<ChartContainer id='tps-graph' title={gettext('Transactions per second')} datasets={props.tpsStats.datasets} errorMsg={props.errorMsg} isTest={props.isTest}>
<StreamingChart data={props.tpsStats} dataPointSize={DATA_POINT_SIZE} xRange={X_AXIS_LENGTH} options={options} />
</ChartContainer>
</DashboardRowCol>
</DashboardRow>
<DashboardRow>
<DashboardRowCol breakpoint='md' parts={4}>
</Grid>
</Grid>
<Grid container spacing={1} style={{marginTop: '4px', marginBottom: '4px'}}>
<Grid item md={4}>
<ChartContainer id='ti-graph' title={gettext('Tuples in')} datasets={props.tiStats.datasets} errorMsg={props.errorMsg} isTest={props.isTest}>
<StreamingChart data={props.tiStats} dataPointSize={DATA_POINT_SIZE} xRange={X_AXIS_LENGTH} options={options} />
</ChartContainer>
</DashboardRowCol>
<DashboardRowCol breakpoint='md' parts={4}>
</Grid>
<Grid item md={4}>
<ChartContainer id='to-graph' title={gettext('Tuples out')} datasets={props.toStats.datasets} errorMsg={props.errorMsg} isTest={props.isTest}>
<StreamingChart data={props.toStats} dataPointSize={DATA_POINT_SIZE} xRange={X_AXIS_LENGTH} options={options} />
</ChartContainer>
</DashboardRowCol>
<DashboardRowCol breakpoint='md' parts={4}>
</Grid>
<Grid item md={4}>
<ChartContainer id='bio-graph' title={gettext('Block I/O')} datasets={props.bioStats.datasets} errorMsg={props.errorMsg} isTest={props.isTest}>
<StreamingChart data={props.bioStats} dataPointSize={DATA_POINT_SIZE} xRange={X_AXIS_LENGTH} options={options} />
</ChartContainer>
</DashboardRowCol>
</DashboardRow>
</Grid>
</Grid>
</>
);
}

View File

@ -117,11 +117,6 @@ class FileManagerModule(PgAdminModule):
LABEL = gettext("Storage")
def get_own_stylesheets(self):
return [
url_for('static', filename='vendor/jquery.dropzone/dropzone.css')
]
def get_own_menuitems(self):
return {
'file_items': []
@ -182,9 +177,9 @@ blueprint = FileManagerModule(MODULE_NAME, __name__)
@blueprint.route("/", endpoint='index')
@login_required
def index():
"""Render the preferences dialog."""
return render_template(
MODULE_NAME + "/index.html", _=gettext)
return bad_request(
errormsg=gettext("This URL cannot be called directly.")
)
@blueprint.route("/utility.js")

View File

@ -1,91 +0,0 @@
<html>
<head>
</head>
<body>
<div class="file_manager d-flex flex-column">
<div id="uploader" class="p-1">
<div class="d-flex">
<div class="flex-grow-1 mr-1">
<div class="input-group" role="group">
<div class="input-group-prepend">
<button name="home" type="button" value="Home" title="{{ _('Home') }}" class="btn btn-primary-icon home"
tabindex="0" aria-label="home">
<span class="fa fa-home sql-icon-lg"></span>
</button>
<button name="level-up" type="button" title="{{ _('Back') }}" value="LevelUp" class="btn btn-primary-icon level-up"
disabled tabindex="0" aria-label="level up">
<span class="fa fa-level-up-alt sql-icon-lg"></span>
</button>
</div>
<input id="file-input-path" class="form-control input-path text-truncate" title="" type="text" tabindex="0" autofocus/>
</div>
<div class="uploadresponse"></div>
</div>
<div>
<input class="mode" name="mode" type="hidden" value="add"/>
<input class="currentpath" name="currentpath" type="hidden"/>
<button type="button" title="{{ _('Refresh') }}" class="btn btn-sm btn-primary-icon refresh"
tabindex="0" aria-label="refresh" id="refresh_list">
<span class="fa fa-sync-alt sql-icon-lg"></span>
</button>
<button type="button" title="{{ _('Download File') }}" class="btn btn-sm btn-primary-icon download"
disabled aria-label="Download File">
<span class="fa fa-download sql-icon-lg"></span>
</button>
<button name="delete" type="button" title="{{ _('Delete File/Folder') }}" class="btn btn-sm btn-primary-icon delete"
disabled aria-label="delete">
<span class="fa fa-trash-alt sql-icon-lg"></span>
</button>
<button name="rename" type="button" title="{{ _('Rename File/Folder') }}" class="btn btn-sm btn-primary-icon rename"
tabindex="0" aria-label="rename">
<span class="fa fa-edit sql-icon-lg"></span>
</button>
<button name="newfolder" type="button" title="{{ _('Create new folder') }}" value="New Folder"
class="btn btn-sm btn-primary-icon create" tabindex="0" aria-label="newfolder">
<span class="fa fa-folder-open sql-icon-lg"></span>
<span class="fa fa-plus add-folder-icon"></span>
</button>
<div class="btn-group" role="group">
<button class="ON btn btn-primary-icon btn-sm grid" type="button" title="{{ _('View as grid') }}" tabindex="0" aria-label="View as grid">
<span class="fa fa-th sql-icon-lg"></span>
</button>
<button type="button" class="btn btn-primary-icon btn-sm list" title="{{ _('View as table') }}" tabindex="0" aria-label="View as table">
<span class="fa fa-list sql-icon-lg"></span>
</button>
</div>
</div>
</div>
</div>
<div class="fileinfo flex-grow-1 d-flex">
<span class="activity">
<img src="{{ url_for('static', filename='img/loading.gif') }}"
alt="{{ _('Loading...') }}">
</span>
<div class="file_listing"></div>
<div class="upload_file d-none"></div>
<div class='fm_dimmer'></div>
<div class='delete_item'>
<span>{{ _('Are you sure you want to delete this item?') }}</span>
<span class="pull-right">
<button type='button' class='btn btn-primary-icon btn_no' tabindex="0">{{ _('No') }}</button>
<button type='button' class='btn btn-primary btn_yes' tabindex="0">{{ _('Yes') }}</button>
</span>
</div>
<div class='replace_file'>
<span>{{ _('Are you sure you want to replace this file?') }}</span>
<span class="pull-right">
<button type='button' class='btn btn-primary-icon btn_no' tabindex="0">{{ _('No') }}</button>
<button type='button' class='btn btn-primary btn_yes' tabindex="0">{{ _('Yes') }}</button>
</span>
</div>
</div>
<div class="allowed_file_types"></div>
<script>
require(['sources/generated/file_utils'], function() {
pgAdmin.FileUtils.init();
});
setTimeout(function(){ $('#file-input-path').focus(); }, 1000);
</script>
</div>
</body>
</html>

View File

@ -1,42 +0,0 @@
{
"LANGUAGE_FILE_NOT_FOUND": "Language file not found.",
"upload_success": "File uploaded successfully.",
"upload_error": "Error uploading file",
"browse": "Browse...",
"bytes": " bytes",
"cancel": "Cancel",
"close": "Close",
"confirmation_delete": "Are you sure you wish to delete this file?",
"current_folder": "",
"del": "Delete",
"download": "Download",
"dz_dictDefaultMessage": "Drop files here to upload",
"dz_dictFallbackMessage": "Your browser does not support drag'n'drop file uploads.",
"dz_dictMaxFilesExceeded": "Only %s simultaneous uploads are allowed.",
"dz_dictInvalidFileType": "You can't upload files of this type.",
"edit": "Edit file",
"file_size_limit": "The file size limit (per file) is ",
"file_too_big": "The file is too big.",
"gb": "gb",
"grid_view": "Switch to grid view.",
"items": "items",
"kb": "kb",
"list_view": "Switch to list view.",
"mb": "mb",
"modified": "Modified",
"move": "Move to ...",
"name": "Name",
"new_folder": "New Folder",
"no": "No",
"no_foldername": "No folder name was provided.",
"rename": "Rename",
"save": "Save",
"select": "Select",
"size": "Size",
"successful_added_folder": "New folder added successfully.",
"successful_delete": "Delete successful.",
"successful_rename": "Rename successful.",
"upload": "Upload",
"yes": "Yes",
"could_not_retrieve_folder": "No files/folders found"
}

View File

@ -167,7 +167,7 @@ export function CollectionNodeView({
})
.then(function (res) {
if (res.success == 0) {
pgBrowser.report_error(res.errormsg, res.info);
Notify.alert(res.errormsg, res.info);
}
pgAdmin.Browser.tree.refresh(selItem);
setReload(!reload);

View File

@ -7,13 +7,13 @@
//
//////////////////////////////////////////////////////////////
import getApiInstance from '../../../static/js/api_instance';
import Notify from '../../../static/js/helpers/Notifier';
import { getBrowser } from '../../../static/js/utils';
define('pgadmin.settings', [
'jquery', 'sources/pgadmin',
'sources/gettext', 'sources/url_for',
], function($, pgAdmin, gettext, url_for) {
'sources/pgadmin', 'sources/gettext', 'sources/url_for',
], function(pgAdmin, gettext, url_for) {
// This defines the Preference/Options Dialog for pgAdmin IV.
pgAdmin = pgAdmin || window.pgAdmin || {};
@ -38,17 +38,13 @@ define('pgadmin.settings', [
Notify.confirm(gettext('Reset layout'),
gettext('Are you sure you want to reset the current layout? This will cause the application to reload and any un-saved data will be lost.'),
function() {
let reloadingIndicator = $('<div id="reloading-indicator"></div>');
$('body').append(reloadingIndicator);
const reloadingIndicator = document.createElement('div');
reloadingIndicator.setAttribute('id', 'reloading-indicator');
document.body.appendChild(reloadingIndicator);
// Delete the record from database as well, then only reload page
$.ajax({
url: url_for('settings.reset_layout'),
type: 'DELETE',
async: false,
})
.done(function() {
// Prevent saving layout on server for next page reload.
$(window).off('unload');
getApiInstance().delete(url_for('settings.reset_layout'))
.then(()=>{
window.onbeforeunload = null;
// Now reload page
location.reload(true);
@ -56,14 +52,12 @@ define('pgadmin.settings', [
if(browser == 'Nwjs') {
pgAdmin.Browser.create_menus();
}
})
.fail(function() {
.catch(()=>{
console.warn(
'Something went wrong on server while resetting layout.'
);
});
},
function() {
// Do nothing as user canceled the operation.

View File

@ -1,10 +1,4 @@
@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';
@import 'node_modules/bootstrap4-toggle/css/bootstrap4-toggle.min.css';
@import 'node_modules/jquery-contextmenu/dist/jquery.contextMenu.css';
@import 'node_modules/webcabin-docker/Build/wcDocker.css';
@import 'node_modules/select2/dist/css/select2.min.css';
@import 'node_modules/leaflet/dist/leaflet.css';
@import 'node_modules/codemirror/lib/codemirror.css';
@ -20,3 +14,6 @@
@import 'node_modules/uplot/dist/uPlot.min.css';
/* wcDocker dependencies */
@import 'node_modules/webcabin-docker/Build/wcDocker.css';
@import 'node_modules/jquery-contextmenu/dist/jquery.contextMenu.css';

View File

@ -99,8 +99,7 @@ export function showServerPassword() {
})
.catch((err)=>{
return onFailure(
err.response.request, status, err, nodeObj, nodeData, treeNodeInfo,
itemNodeData, status
err, nodeObj, nodeData, treeNodeInfo, itemNodeData, status
);
});
}}
@ -141,7 +140,7 @@ export function showSchemaDiffServerPassword() {
})
.catch((err)=>{
return onFailure(
err.response.request, status, err, serverID, successCallback
err, serverID, successCallback
);
});
}}
@ -165,8 +164,8 @@ export function checkMasterPassword(data, masterpass_callback_queue, cancel_call
} else {
masterPassCallbacks(masterpass_callback_queue);
}
}).catch(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error);
}).catch(function(error) {
Notify.pgRespErrorNotify(error);
});
}
@ -288,8 +287,8 @@ export function showNamedRestorePoint() {
onClose();
Notify.success(res.data.data.result);
})
.catch(function(xhr, status, error) {
Notify.pgRespErrorNotify(xhr, error);
.catch(function(error) {
Notify.pgRespErrorNotify(error);
});
}}
/>

View File

@ -20,6 +20,7 @@ import HelpIcon from '@material-ui/icons/HelpRounded';
import EditIcon from '@material-ui/icons/Edit';
import diffArray from 'diff-arrays-of-objects';
import _ from 'lodash';
import clsx from 'clsx';
import {FormFooterMessage, MESSAGE_TYPE } from 'sources/components/FormComponents';
import { PrimaryButton, DefaultButton, PgIconButton } from 'sources/components/Buttons';
@ -52,6 +53,9 @@ const useDialogStyles = makeStyles((theme)=>({
display: 'flex',
flexDirection: 'column',
},
formProperties: {
backgroundColor: theme.palette.grey[400],
},
footer: {
padding: theme.spacing(1),
background: theme.otherVars.headerBg,
@ -990,7 +994,7 @@ function SchemaPropertiesView({
<PgIconButton data-test="edit"
onClick={props.onEdit} icon={<EditIcon />} title="Edit the object" />
</Box>
<Box className={classes.form}>
<Box className={clsx(classes.form, classes.formProperties)}>
<Box>
{Object.keys(finalTabs).map((tabName)=>{
let id = tabName.replace(' ', '');

View File

@ -515,6 +515,7 @@ function getFinalTheme(baseTheme) {
root: {
padding: '4px 8px',
backgroundColor: baseTheme.otherVars.cardHeaderBg,
fontWeight: 'bold',
...mixins.panelBorder.bottom,
}
},

View File

@ -86,7 +86,7 @@ PgMenu.propTypes = {
className: CustomPropTypes.className,
label: PropTypes.string,
anchorRef: CustomPropTypes.ref,
menuButton: PropTypes.oneOfType([React.ReactNode, undefined]),
menuButton: PropTypes.element,
};
export const PgSubMenu = applyStatics(SubMenu)(({label, ...props})=>{

View File

@ -7,7 +7,6 @@
//
//////////////////////////////////////////////////////////////
import $ from 'jquery';
import axios from 'axios';
export function setPGCSRFToken(header, token) {
@ -16,14 +15,6 @@ export function setPGCSRFToken(header, token) {
throw new Error('csrf-token meta tag has not been set');
}
// Configure jquery.ajax to set 'X-CSRFToken' request header for
// every requests.
$.ajaxSetup({
beforeSend: function(xhr) {
xhr.setRequestHeader(header, token);
},
});
// Configure axios to set 'X-CSRFToken' request header for
// every requests.
axios.interceptors.request.use(function (config) {

View File

@ -1,154 +0,0 @@
/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2023, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import $ from 'jquery';
import Mousetrap from 'mousetrap';
import { findAndSetFocus, parseShortcutValue } from './utils';
class dialogTabNavigator {
constructor(dialogContainer, backwardShortcut, forwardShortcut) {
this.dialogContainer = dialogContainer;
this.tabSwitching = false;
this.tabs = this.dialogContainer.find('.nav-tabs:visible');
if (this.tabs.length > 0 ) {
this.tabs = this.tabs[0];
}
this.dialogTabBackward = parseShortcutValue(backwardShortcut);
this.dialogTabForward = parseShortcutValue(forwardShortcut);
Mousetrap(this.dialogContainer[0]).bind(this.dialogTabBackward, this.onKeyboardEvent.bind(this));
Mousetrap(this.dialogContainer[0]).bind(this.dialogTabForward, this.onKeyboardEvent.bind(this));
}
onKeyboardEvent(event, shortcut) {
let currentTabPane = this.dialogContainer
.find('.tab-content:first > .tab-pane.active:first:visible'),
childTabData = this.isActivePaneHasChildTabs(currentTabPane);
if (this.tabSwitching) {
return;
}
this.tabSwitching = true;
if(childTabData) {
let res = this.navigate(shortcut, childTabData.childTab,
childTabData.childTabPane, event);
if (!res) {
this.navigate(shortcut, this.tabs, currentTabPane, event);
}
} else {
this.navigate(shortcut, this.tabs, currentTabPane, event);
}
}
isActivePaneHasChildTabs(currentTabPane) {
let childTab = currentTabPane.find('.nav-tabs:first:visible'),
childTabPane;
if (childTab.length > 0) {
childTabPane = currentTabPane
.find('.tab-content:first > .tab-pane.active:first:visible');
return {
'childTab': childTab,
'childTabPane': childTabPane,
};
}
return null;
}
navigate(shortcut, tabs, tab_pane, event) {
if (shortcut == this.dialogTabBackward) {
return this.navigateBackward(tabs, tab_pane, event);
} else if (shortcut == this.dialogTabForward) {
return this.navigateForward(tabs, tab_pane, event);
}
return false;
}
navigateBackward(tabs, tab_pane, event) {
let self = this,
nextTabPane,
innerTabContainer,
prevtab = $(tabs).find('li').has('a.active').prev('li');
if (prevtab.length > 0) {
prevtab.find('a').tab('show');
nextTabPane = tab_pane.prev();
innerTabContainer = nextTabPane
.find('.tab-content:first > .tab-pane.active:first:visible');
if (innerTabContainer.length > 0) {
findAndSetFocus(innerTabContainer);
} else {
findAndSetFocus(nextTabPane);
}
setTimeout(function() {
self.tabSwitching = false;
}, 200);
event.stopPropagation();
return true;
}
this.tabSwitching = false;
return false;
}
navigateForward(tabs, tab_pane, event) {
let self = this,
nextTabPane,
innerTabContainer,
nexttab = $(tabs).find('li').has('a.active').next('li');
if(nexttab.length > 0) {
nexttab.find('a').tab('show');
nextTabPane = tab_pane.next();
innerTabContainer = nextTabPane
.find('.tab-content:first > .tab-pane.active:first:visible');
if (innerTabContainer.length > 0) {
findAndSetFocus(innerTabContainer);
} else {
findAndSetFocus(nextTabPane);
}
setTimeout(function() {
self.tabSwitching = false;
}, 200);
event.stopPropagation();
return true;
}
this.tabSwitching = false;
return false;
}
detach() {
Mousetrap(this.dialogContainer[0]).unbind(this.dialogTabBackward);
Mousetrap(this.dialogContainer[0]).unbind(this.dialogTabForward);
}
}
module.exports = {
dialogTabNavigator: dialogTabNavigator,
};

View File

@ -24,6 +24,7 @@ import gettext from 'sources/gettext';
import _ from 'lodash';
import pgWindow from 'sources/window';
import ModalProvider, { useModal } from './ModalProvider';
import { parseApiError } from '../api_instance';
const AUTO_HIDE_DURATION = 3000; // In milliseconds
@ -150,76 +151,45 @@ let Notifier = {
);
},
pgRespErrorNotify(xhr, error, prefixMsg='') {
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);
pgRespErrorNotify(error, prefixMsg='') {
if (error.response?.status === 410) {
this.alert(gettext('Error: Object not found - %s.', error.response.statusText), parseApiError(error));
} else {
try {
if (xhr.status === 0) {
error = gettext('Connection to the server has been lost.');
} else {
if(contentType){
if(contentType.indexOf('application/json') >= 0) {
let resp = JSON.parse(xhr.responseText);
error = _.escape(resp.result) || _.escape(resp.errormsg) || gettext('Unknown error');
}
}
if (contentType.indexOf('text/html') >= 0) {
error = gettext('INTERNAL SERVER ERROR');
console.warn(xhr.responseText);
}
}
}
catch(e){
error = e.message;
}
this.error(prefixMsg + ' ' + error);
this.error(prefixMsg + ' ' + parseApiError(error));
}
},
pgNotifier(type, xhr, promptmsg, onJSONResult) {
let msg = xhr.responseText,
contentType = xhr.getResponseHeader('Content-Type');
pgNotifier(type, error, promptmsg, onJSONResult) {
let msg;
if (xhr.status == 0) {
msg = gettext('Connection to the server has been lost.');
if(!error.response) {
msg = parseApiError(error);
promptmsg = gettext('Connection Lost');
} else {
if (contentType) {
try {
if (contentType.indexOf('application/json') == 0) {
let resp = JSON.parse(msg);
if(resp.info == 'CRYPTKEY_MISSING') {
let pgBrowser = window.pgAdmin.Browser;
pgBrowser.set_master_password('', ()=> {
if(onJSONResult && typeof(onJSONResult) == 'function') {
onJSONResult('CRYPTKEY_SET');
}
}, ()=> {
if(onJSONResult && typeof(onJSONResult) == 'function') {
onJSONResult('CRYPTKEY_NOT_SET');
}
});
return;
} else if (resp.result != null && (!resp.errormsg || resp.errormsg == '') &&
onJSONResult && typeof(onJSONResult) == 'function') {
return onJSONResult(resp.result);
if(error.response.headers['content-type'] == 'application/json') {
let resp = error.response.data;
if(resp.info == 'CRYPTKEY_MISSING') {
let pgBrowser = window.pgAdmin.Browser;
pgBrowser.set_master_password('', ()=> {
if(onJSONResult && typeof(onJSONResult) == 'function') {
onJSONResult('CRYPTKEY_SET');
}
msg = _.escape(resp.result) || _.escape(resp.errormsg) || 'Unknown error';
}
if (contentType.indexOf('text/html') == 0) {
if (type === 'error') {
this.alert('Error', promptmsg);
}, ()=> {
if(onJSONResult && typeof(onJSONResult) == 'function') {
onJSONResult('CRYPTKEY_NOT_SET');
}
return;
}
} catch (e) {
this.alert('Error', e.message);
});
return;
} else if (resp.result != null && (!resp.errormsg || resp.errormsg == '') &&
onJSONResult && typeof(onJSONResult) == 'function') {
return onJSONResult(resp.result);
}
msg = _.escape(resp.result) || _.escape(resp.errormsg) || 'Unknown error';
} else {
if (type === 'error') {
this.alert('Error', promptmsg);
}
return;
}
}
this.alert(promptmsg, msg.replace(new RegExp(/\r?\n/, 'g'), '<br />'));

View File

@ -125,6 +125,9 @@ const useStyles = makeStyles((theme) =>
padding: '8px',
display: 'flex',
flexDirection: 'column',
},
hidden: {
display: 'none',
}
}),
);
@ -198,7 +201,7 @@ function Wizard({ stepList, onStepChange, onSave, className, ...props }) {
{
React.Children.map(props.children, (child) => {
return (
<div hidden={child.props.stepId !== activeStep} className={clsx(classes.stepDefaultStyle, child.props.className)}>
<div className={clsx(classes.stepDefaultStyle, child.props.className, (child.props.stepId !== activeStep ? classes.hidden : ''))}>
{child}
</div>
);

View File

@ -7,19 +7,9 @@
//
//////////////////////////////////////////////////////////////////////////
import $ from 'jquery';
import gettext from 'sources/gettext';
import { getMod } from 'sources/utils';
const PERIOD_KEY = 190,
FWD_SLASH_KEY = 191,
ESC_KEY = 27,
LEFT_KEY = 37,
UP_KEY = 38,
RIGHT_KEY = 39,
DOWN_KEY = 40,
K_KEY = 75;
function isMac() {
return window.navigator.userAgentData?.platform === 'macOS'
|| window.navigator.platform.search('Mac') != -1;
@ -154,211 +144,8 @@ function focusDockerPanel(docker, op) {
return focus_panel._type;
}
/* Debugger: Keyboard Shortcuts handling */
function keyboardShortcutsDebugger($el, event, preferences, docker) {
let panel_type = '', panel_content, $input;
if(this.validateShortcutKeys(preferences.edit_grid_values, event)) {
this._stopEventPropagation(event);
panel_content = $el.find(
'div.wcPanelTabContent:not(".wcPanelTabContentHidden")'
);
if(panel_content.length) {
$input = $(panel_content).find('td.editable:first');
if($input.length)
$input.trigger('click');
}
} else if(this.validateShortcutKeys(preferences.move_next, event)) {
this._stopEventPropagation(event);
panel_type = focusDockerPanel(docker, 'right');
} else if(this.validateShortcutKeys(preferences.move_previous, event)) {
this._stopEventPropagation(event);
panel_type = focusDockerPanel(docker, 'left');
} else if(this.validateShortcutKeys(preferences.switch_panel, event)) {
this._stopEventPropagation(event);
panel_type = focusDockerPanel(docker, 'switch');
}
return panel_type;
}
/* Query tool: Keyboard Shortcuts handling */
function keyboardShortcutsQueryTool(
sqlEditorController, queryToolActions, event, docker
) {
if (sqlEditorController.isQueryRunning()) {
return;
}
let keyCode = event.which || event.keyCode, panel_type = '';
let executeKeys = sqlEditorController.preferences.execute_query;
let explainKeys = sqlEditorController.preferences.explain_query;
let explainAnalyzeKeys = sqlEditorController.preferences.explain_analyze_query;
let downloadCsvKeys = sqlEditorController.preferences.download_results;
let nextTabKeys = sqlEditorController.preferences.move_next;
let previousTabKeys = sqlEditorController.preferences.move_previous;
let switchPanelKeys = sqlEditorController.preferences.switch_panel;
let toggleCaseKeys = sqlEditorController.preferences.toggle_case;
let commitKeys = sqlEditorController.preferences.commit_transaction;
let rollbackKeys = sqlEditorController.preferences.rollback_transaction;
let saveDataKeys = sqlEditorController.preferences.save_data;
let queryToolKeys = sqlEditorController.preferences.show_query_tool;
if (this.validateShortcutKeys(executeKeys, event)) {
this._stopEventPropagation(event);
queryToolActions.executeQuery(sqlEditorController);
} else if (this.validateShortcutKeys(explainKeys, event)) {
this._stopEventPropagation(event);
queryToolActions.explain(sqlEditorController);
} else if (this.validateShortcutKeys(explainAnalyzeKeys, event)) {
this._stopEventPropagation(event);
queryToolActions.explainAnalyze(sqlEditorController);
} else if (this.validateShortcutKeys(downloadCsvKeys, event)) {
if(!sqlEditorController.is_save_results_to_file_disabled) {
this._stopEventPropagation(event);
queryToolActions.download(sqlEditorController);
}
} else if (this.validateShortcutKeys(toggleCaseKeys, event)) {
this._stopEventPropagation(event);
queryToolActions.toggleCaseOfSelectedText(sqlEditorController);
} else if (this.validateShortcutKeys(commitKeys, event)) {
// If transaction buttons are disabled then no need to execute commit.
if (!sqlEditorController.is_transaction_buttons_disabled) {
this._stopEventPropagation(event);
queryToolActions.executeCommit(sqlEditorController);
}
} else if (this.validateShortcutKeys(rollbackKeys, event)) {
// If transaction buttons are disabled then no need to execute rollback.
if (!sqlEditorController.is_transaction_buttons_disabled) {
this._stopEventPropagation(event);
queryToolActions.executeRollback(sqlEditorController);
}
} else if (this.validateShortcutKeys(saveDataKeys, event)) {
this._stopEventPropagation(event);
queryToolActions.saveDataChanges(sqlEditorController);
} else if (this.validateShortcutKeys(queryToolKeys, event)) {
this._stopEventPropagation(event);
queryToolActions.openQueryTool(sqlEditorController);
} else if ((
(this.isMac() && event.metaKey) ||
(!this.isMac() && event.ctrlKey)
) && !event.altKey && event.shiftKey && keyCode === FWD_SLASH_KEY) {
this._stopEventPropagation(event);
queryToolActions.commentBlockCode(sqlEditorController);
} else if ((
(this.isMac() && !this.isKeyCtrlAltShift(event) && event.metaKey) ||
(!this.isMac() && !this.isKeyAltShift(event) && event.ctrlKey)
) && keyCode === FWD_SLASH_KEY) {
this._stopEventPropagation(event);
queryToolActions.commentLineCode(sqlEditorController);
} else if ((
(this.isMac() && !this.isKeyCtrlAltShift(event) && event.metaKey) ||
(!this.isMac() && !this.isKeyAltShift(event) && event.ctrlKey)
) && keyCode === PERIOD_KEY) {
this._stopEventPropagation(event);
queryToolActions.uncommentLineCode(sqlEditorController);
} else if ((
(this.isMac() && event.metaKey) ||
(!this.isMac() && event.ctrlKey)
) && !event.altKey && event.shiftKey && keyCode === K_KEY) {
this._stopEventPropagation(event);
queryToolActions.formatSql(sqlEditorController);
} else if (keyCode == ESC_KEY) {
queryToolActions.focusOut(sqlEditorController);
/*Apply only for sub-dropdown*/
if($(event.target).hasClass('dropdown-item')
&& $(event.target).closest('.dropdown-submenu').length > 0) {
$(event.target).closest('.dropdown-submenu').find('.dropdown-menu').removeClass('show');
}
} else if(this.validateShortcutKeys(nextTabKeys, event)) {
this._stopEventPropagation(event);
panel_type = focusDockerPanel(docker, 'right');
} else if(this.validateShortcutKeys(previousTabKeys, event)) {
this._stopEventPropagation(event);
panel_type = focusDockerPanel(docker, 'left');
} else if(this.validateShortcutKeys(switchPanelKeys, event)) {
this._stopEventPropagation(event);
panel_type = focusDockerPanel(docker, 'switch');
} else if(keyCode === UP_KEY || keyCode === DOWN_KEY) {
/*Apply only for dropdown*/
if($(event.target).closest('.dropdown-menu').length > 0) {
this._stopEventPropagation(event);
let currLi = $(event.target).closest('li');
/*close all the submenus on movement*/
$(event.target).closest('.dropdown-menu').find('.show').removeClass('show');
if(keyCode === UP_KEY) {
currLi = currLi.prev();
}
else if(keyCode === DOWN_KEY){
currLi = currLi.next();
}
/*do not focus on divider, disabled and d-none */
while(currLi.hasClass('dropdown-divider')
|| currLi.hasClass('d-none')
|| currLi.find('.dropdown-item').first().hasClass('disabled')) {
if(keyCode === UP_KEY) {
currLi = currLi.prev();
}
else if(keyCode === DOWN_KEY){
currLi = currLi.next();
}
}
currLi.find('.dropdown-item').trigger('focus');
}
} else if(keyCode === LEFT_KEY || keyCode === RIGHT_KEY) {
/*Apply only for dropdown*/
if($(event.target).closest('.dropdown-menu').length > 0) {
this._stopEventPropagation(event);
let currLi = $(event.target).closest('li');
if(keyCode === RIGHT_KEY) {
/*open submenu if any*/
if(currLi.hasClass('dropdown-submenu')){
currLi.find('.dropdown-menu').addClass('show');
currLi.find('.dropdown-menu .dropdown-item').first().trigger('focus');
}
} else if(keyCode === LEFT_KEY) {
/*close submenu*/
let currMenu = currLi.closest('.dropdown-menu');
if(currMenu.closest('.dropdown-submenu').length > 0) {
currMenu.removeClass('show');
currLi = currMenu.closest('.dropdown-submenu');
currLi.find('.dropdown-item').trigger('focus');
}
}
}
} else {
// Macros
let macroId = this.validateMacros(sqlEditorController, event);
if (macroId !== false) {
this._stopEventPropagation(event);
queryToolActions.executeMacro(sqlEditorController, macroId);
}
}
return panel_type;
}
function validateMacros(sqlEditorController, event) {
let keyCode = event.which || event.keyCode;
let macro = sqlEditorController.macros.filter(mc =>
mc.alt == event.altKey &&
mc.control == event.ctrlKey &&
mc.key_code == keyCode);
if (macro.length == 1) {
return macro[0].id;
}
return false;
}
export {
keyboardShortcutsDebugger as processEventDebugger,
keyboardShortcutsQueryTool as processEventQueryTool,
focusDockerPanel, validateShortcutKeys, validateMacros,
focusDockerPanel, validateShortcutKeys,
_stopEventPropagation, isMac, isKeyCtrlAlt, isKeyAltShift, isKeyCtrlShift,
isKeyCtrlAltShift, isAltShiftBoth, isCtrlShiftBoth, isCtrlAltBoth,
shortcut_key, shortcut_title, shortcut_accesskey_title,

View File

@ -8,10 +8,10 @@
//////////////////////////////////////////////////////////////
import _ from 'lodash';
import $ from 'jquery';
import url_for from 'sources/url_for';
import gettext from 'sources/gettext';
import pgAdmin from 'sources/pgadmin';
import getApiInstance from '../api_instance';
export const pgBrowser = pgAdmin.Browser = pgAdmin.Browser || {};
@ -72,23 +72,10 @@ _.extend(pgBrowser.browserTreeState, {
pgBrowser.Events.on('pgadmin:browser:tree:update-tree-state',
this.update_cache.bind(this));
} else if (!_.isUndefined(save_tree_state_period)) {
$.ajax({
url: url_for('settings.reset_tree_state'),
type: 'DELETE',
})
.fail(function(jqx) {
let msg = jqx.responseText;
/* Error from the server */
if (jqx.status == 417 || jqx.status == 410 || jqx.status == 500) {
try {
let data = JSON.parse(jqx.responseText);
msg = data.errormsg;
} catch (e) {
console.warn(e.stack || e);
}
}
getApiInstance().delete(url_for('settings.reset_tree_state'))
.catch(function(error) {
console.warn(
gettext('Error resetting the tree saved state."'), msg);
gettext('Error resetting the tree saved state."'), error);
});
}
@ -99,58 +86,29 @@ _.extend(pgBrowser.browserTreeState, {
if(self.last_state == JSON.stringify(self.current_state))
return;
$.ajax({
url: url_for('settings.save_tree_state'),
type: 'POST',
contentType: 'application/json',
data: JSON.stringify(self.current_state),
})
.done(function() {
self.last_state = JSON.stringify(self.current_state);
self.fetch_state();
})
.fail(function(jqx) {
let msg = jqx.responseText;
/* Error from the server */
if (jqx.status == 417 || jqx.status == 410 || jqx.status == 500) {
try {
let data = JSON.parse(jqx.responseText);
msg = data.errormsg;
} catch (e) {
console.warn(e.stack || e);
}
}
console.warn(
gettext('Error saving the tree state."'), msg);
});
getApiInstance().post(
url_for('settings.save_tree_state'),
JSON.stringify(self.current_state)
).then(()=> {
self.last_state = JSON.stringify(self.current_state);
self.fetch_state();
}).catch(function(error) {
console.warn(
gettext('Error resetting the tree saved state."'), error);
});
},
fetch_state: function() {
let self = this;
$.ajax({
url: url_for('settings.get_tree_state'),
type: 'GET',
dataType: 'json',
contentType: 'application/json',
})
.done(function(res) {
self.stored_state = res;
})
.fail(function(jqx) {
let msg = jqx.responseText;
/* Error from the server */
if (jqx.status == 417 || jqx.status == 410 || jqx.status == 500) {
try {
let data = JSON.parse(jqx.responseText);
msg = data.errormsg;
} catch (e) {
console.warn(e.stack || e);
}
}
console.warn(
gettext('Error fetching the tree state.'), msg);
});
getApiInstance().get(
url_for('settings.get_tree_state'),
).then((res)=> {
self.stored_state = res.data;
}).catch(function(error) {
console.warn(
gettext('Error resetting the tree saved state."'), error);
});
},
update_cache: function(item) {
let data = item && pgBrowser.tree.itemData(item),

View File

@ -8,7 +8,6 @@
//////////////////////////////////////////////////////////////////////////
import _ from 'lodash';
import $ from 'jquery';
import pgAdmin from 'sources/pgadmin';
import { FileType } from 'react-aspen';
@ -533,17 +532,15 @@ export class Tree {
}
/* setDragImage is not supported in IE. We leave it to
* its default look and feel
*/
* its default look and feel
*/
if (e.dataTransfer.setDragImage) {
let dragItem = $(`
<div class="drag-tree-node">
<span>${_.escape(dropDetails.text)}</span>
</div>`
);
const dragItem = document.createElement('div');
dragItem.setAttribute('drag-tree-node');
dragItem.innerHTML = `<span>${_.escape(dropDetails.text)}</span>`;
$('body .drag-tree-node').remove();
$('body').append(dragItem);
document.querySelector('body .drag-tree-node').remove();
document.body.appendChild(dragItem);
e.dataTransfer.setDragImage(dragItem[0], 0, 0);
}

View File

@ -8,7 +8,6 @@
//////////////////////////////////////////////////////////////////////////
import _ from 'lodash';
import $ from 'jquery';
import url_for from './url_for';
import gettext from 'sources/gettext';
import 'wcdocker';
@ -28,64 +27,6 @@ export function parseShortcutValue(obj) {
return shortcut;
}
export function handleKeyNavigation(event) {
let wizardHeader = $(event.currentTarget).find('.wizard-header');
let wizardFooter = $(event.currentTarget).find('.wizard-footer');
let gridElement = $(event.currentTarget).find('.select-row-cell:first');
let gridElementLast = $(event.currentTarget).find('.select-row-cell:last');
let firstWizardHeaderButton = $(wizardHeader).find('button:enabled:first');
let lastWizardHeaderButton = $(wizardHeader).find('button:enabled:last');
let lastWizardFooterBtn = $(wizardFooter).find('button:enabled:last');
let firstWizardFooterBtn = $(wizardFooter).find('button:enabled:first');
if (event.shiftKey && event.keyCode === 9) {
// Move backwards
if(firstWizardHeaderButton && $(firstWizardHeaderButton).is($(event.target))) {
if (lastWizardFooterBtn) {
$(lastWizardFooterBtn).focus();
event.preventDefault();
event.stopPropagation();
}
}
else if ($(firstWizardFooterBtn).is($(event.target))){
if ($(gridElement).find('.custom-control-input').is(':visible')){
$(gridElementLast).find('.custom-control-input').focus();
event.preventDefault();
event.stopPropagation();
}else if ($(event.currentTarget).find('.wizard-content').find('.CodeMirror-scroll').is(':visible')){
$(lastWizardHeaderButton).focus();
}
}
} else if (event.keyCode === 9) {
// Move forwards
// If taget is last button then goto first element
if(lastWizardFooterBtn && $(lastWizardFooterBtn).is($(event.target))) {
$(firstWizardHeaderButton).focus();
event.preventDefault();
event.stopPropagation();
}else if (event.target.innerText == 'Name'){
if ($(gridElement).find('.custom-control-input').is(':visible')){
$(gridElement).find('.custom-control-input').focus();
}else {
$(firstWizardFooterBtn).focus();
}
event.preventDefault();
event.stopPropagation();
} else if(event.target.tagName == 'DIV') {
$(event.currentTarget).find('.custom-control-input:first').trigger('focus');
event.preventDefault();
event.stopPropagation();
} else if(event.target.tagName == 'TEXTAREA'){
$(firstWizardFooterBtn).focus();
}
} else if (event.keyCode === 27){
//close the wizard when esc key is pressed
$(wizardHeader).find('button.ajs-close').click();
}
}
export function findAndSetFocus(container) {
if (container.length == 0) {
return;
@ -425,25 +366,28 @@ export function evalFunc(obj, func, param) {
}
export function registerDetachEvent(panel){
panel.on(wcDocker.EVENT.DETACHED, function() {
$((this.$container)[0].ownerDocument).find('.wcIFrameFloating').attr({
style: 'z-index: 1200'
});
});
panel.on(wcDocker.EVENT.ORDER_CHANGED, function() {
function updateIframePosition() {
let docker = this.docker(this._panel);
let dockerPos = docker.$container.offset();
let pos = this.$container.offset();
let width = this.$container.width();
let height = this.$container.height();
let zIndex = window.getComputedStyle(this._parent.$frame[0]).getPropertyValue('z-index');
$((this.$container)[0].ownerDocument).find('.wcIFrameFloating').css('top', pos.top - dockerPos.top);
$((this.$container)[0].ownerDocument).find('.wcIFrameFloating').css('left', pos.left - dockerPos.left);
$((this.$container)[0].ownerDocument).find('.wcIFrameFloating').css('width', width);
$((this.$container)[0].ownerDocument).find('.wcIFrameFloating').find('.wcIFrameFloating').css('height', height);
$((this.$container)[0].ownerDocument).find('.wcIFrameFloating').attr({
style: 'z-index: 1200'
});
let ele = this.$container[0].ownerDocument.querySelector('.wcIFrameFloating');
if(ele) {
ele.style.top = pos.top - dockerPos.top;
ele.style.left = pos.left - dockerPos.left;
ele.style.width = width;
ele.style.height = height;
ele.style.zIndex = parseInt(zIndex)+1;
}
}
panel.on(wcDocker.EVENT.DETACHED, function() {
updateIframePosition.call(this);
});
panel.on(wcDocker.EVENT.ORDER_CHANGED, function() {
updateIframePosition.call(this);
});
}
@ -537,127 +481,123 @@ export function calcFontSize(fontSize) {
return '1em';
}
export function pgHandleItemError(xhr, args) {
export function pgHandleItemError(error, args) {
let pgBrowser = window.pgAdmin.Browser;
if (!xhr || !pgBrowser) {
if (!error || !pgBrowser) {
return;
}
let 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(error.response.headers['content-type'] == 'application/json') {
let jsonResp = error.response.data;
if (
args.preHandleConnectionLost &&
typeof(args.preHandleConnectionLost) == 'function'
jsonResp && (
error.response.status == 503 ? (
jsonResp.info == 'CONNECTION_LOST' &&
'server' in args.info && jsonResp.data.sid >= 0 &&
jsonResp.data.sid == args.info.server._id
) : (
error.response.status == 428 &&
jsonResp.errormsg &&
jsonResp.errormsg == gettext('Connection to the server has been lost.')
)
)
) {
args.preHandleConnectionLost.apply(this, arguments);
}
if (
args.preHandleConnectionLost &&
typeof(args.preHandleConnectionLost) == 'function'
) {
args.preHandleConnectionLost.apply(this, arguments);
}
// Check the status of the maintenance server connection.
let server = pgBrowser.Nodes['server'],
ctx = {
resp: jsonResp,
xhr: xhr,
args: args,
},
reconnectServer = function() {
let 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
);
// Check the status of the maintenance server connection.
let server = pgBrowser.Nodes['server'],
ctx = {
resp: jsonResp,
error: error,
args: args,
},
reconnectServer = function() {
let 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.
// 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:connection:lost', this.args.item,
this.resp, true
'pgadmin:database:connect:cancelled', _sid,
this.resp.data.database || _data.db, _item, _data
);
}
}
}.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);
}.bind(ctx_local);
// 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);
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);
// 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(
getApiInstance().get(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;
))
.then(({data: 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;
// Server was not connected, we should first try to connect
// the server.
reconnectServer();
})
.catch(()=>{
reconnectServer();
});
return true;
} else if (jsonResp && jsonResp.info == 'CRYPTKEY_MISSING' && error.response.status == 503) {
/* Suppress the error here and handle in pgNotifier wherever
* required, as it has callback option
*/
return false;
}
}
return false;
}

View File

@ -1,182 +0,0 @@
.alert-icon {
display: flex;
align-items: center;
color: $alert-icon-color;
padding: 15px 15px 15px 17px;
width: 50px;
min-height: 50px;
font-size: 14px;
text-align: center;
align-self: stretch;
flex-shrink: 0;
}
.alert-row {
display: block;
width: auto;
}
.alert-box {
padding: 0px;
display: inline-block;
}
.alert.alert-info,
.alert.alert-danger {
padding: 0.5rem;
}
.success-icon {
background: $color-success;
}
.error-icon {
background: $color-danger;
}
.info-icon {
background: $color-primary;
}
.alert-text {
display: inline-block;
padding: 0 12px 0 10px;
align-self: center;
// To make sure IE picks up the correct font
font-family: $font-family-primary;
color: $alert-color-fg;
}
.alert-info {
border-color: $color-primary;
background-color: $color-primary-light;
color : $color-fg;
background-image: none;
}
.alert-danger {
background-image: none;
}
.grid-error, .graph-error {
.alert-row {
align-items: center;
height: 100%;
display: flex;
justify-content: center;
}
}
.ajs-message {
.media {
display: block;
}
}
.alert, .ajs-message {
.media {
.media-body {
display: inline-block;
width: auto;
.alert-icon {
display: inline-block;
}
.alert-text {
display: inline-block;
}
}
}
}
.error-in-grid {
border-radius: $border-radius !important;
background: $alert-danger-bg !important;
color: $alert-danger-color !important;
}
.pg-prop-status-bar {
padding: 5px;
.media-body {
display: flex;
width: auto;
}
.alert-icon {
padding: 8px 8px 8px 10.5px;
width: 35px;
height: 35px;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
min-height: auto;
}
.alert-text {
-moz-user-select: text;
-khtml-user-select: text;
-webkit-user-select: text;
-ms-user-select: text;
user-select: text;
}
.error-in-footer {
border-radius: $border-radius;
background: $alert-danger-bg;
border: $border-width solid $alert-danger-color;
color: $alert-danger-color;
}
.success-in-footer {
border-radius: $border-radius;
background: $alert-success-bg;
border: $border-width solid $alert-success-color;
color: $alert-success-color;
}
.info-in-footer {
border-radius: $border-radius;
background: $alert-primary-bg;
border: $border-width solid $alert-primary-color;
color: $alert-primary-color;
.fa {
font-size: 1rem;
}
}
}
//Internet Explorer specific CSS
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {
.styleguide {
.alert-danger {
width: auto;
}
.alert-info {
width: auto;
}
}
.alert-danger {
width: 90%;
}
.alert-info {
width: 90%;
}
}
/* To align 'X' in alert on login page */
.alert-dismissable, .alert-dismissible {
padding-right: 35px !important;
}
.alert-info-panel {
border: 2px solid $color-gray-light;
margin-top: 2em;
padding: 5px 5px;
background: $color-gray-lighter;
border-radius: 5px;
height: 8em;
overflow: scroll;
}

View File

@ -1,29 +0,0 @@
.toggle.btn-xs {
min-width: 3rem; min-height: 1.5rem;
}
.toggle-on.btn-xs {
padding-right: .8rem;
}
.toggle-off.btn-xs {
padding-left: .8rem;
}
.btn-xs, .btn-group-xs > .btn, .btn-xs-sq {
padding: 0.05rem 0.4rem;
font-size: 0.76562rem;
line-height: 1.5;
border-radius: 0.2rem;
}
.toggle input[type="checkbox"] {
display: block;
opacity: 0;
margin-top: 0px !important;
}
.toggle:focus-within {
border-color: $input-focus-border-color !important;
outline: 0;
-webkit-box-shadow: $input-focus-box-shadow;
box-shadow: $input-focus-box-shadow;
}

View File

@ -1,92 +0,0 @@
/* The Bootstrap default grid layout is based on @media - window size
* But in pgadmin4, we need to resize/make responsive elements based on panel size
* which can be changed by wcDocker. Below code will generate pg-el-* classes
* using the bootstrap grid classes generator. Based on el attribute of pg-el-container div,
* the classes will apply.el attribute is set in /pgadmin4/web/pgadmin/browser/static/js/panel.js
*
* Code reused and customized from : bootstrap/scss/mixins/_grid-framework.scss
*/
@mixin make-grid-columns($columns: $grid-columns, $gutter: $grid-gutter-width, $breakpoints: $grid-breakpoints) {
// Common properties for all breakpoints
%grid-column {
position: relative;
width: 100%;
padding-right: math.div($gutter, 2);
padding-left: math.div($gutter, 2);
}
@each $breakpoint in map-keys($breakpoints) {
$infix: breakpoint-infix($breakpoint, $breakpoints);
// Allow columns to stretch full width below their breakpoints
@for $i from 1 through $columns {
.pg-el#{$infix}-#{$i} {
@extend %grid-column;
}
}
.pg-el-container[el=xs]
.pg-el#{$infix},
.pg-el-container[el=xs]
.pg-el#{$infix}-auto {
@extend %grid-column;
}
// Provide basic `.pg-el-{bp}` classes for equal-width flexbox columns
.pg-el-container[el=xs]
.pg-el#{$infix} {
flex-basis: 0;
flex-grow: 1;
max-width: 100%;
}
}
@for $i from 1 through $columns {
.pg-el-container[el=xl] {
.pg-el-sm-#{$i} {
@include make-col($i, $columns);
}
.pg-el-md-#{$i} {
@include make-col($i, $columns);
}
.pg-el-lg-#{$i} {
@include make-col($i, $columns);
}
.pg-el-xl-#{$i} {
@include make-col($i, $columns);
}
}
.pg-el-container[el=lg] {
.pg-el-sm-#{$i} {
@include make-col($i, $columns);
}
.pg-el-md-#{$i} {
@include make-col($i, $columns);
}
.pg-el-lg-#{$i} {
@include make-col($i, $columns);
}
}
.pg-el-container[el=md] {
.pg-el-md-#{$i} {
@include make-col($i, $columns);
}
.pg-el-sm-#{$i} {
@include make-col($i, $columns);
}
}
.pg-el-container[el=sm] {
.pg-el-sm-#{$i} {
@include make-col($i, $columns);
}
}
}
}
@include make-grid-columns();

View File

@ -221,45 +221,18 @@
height: auto !important;
}
.obj_properties .backform-tab {
position: absolute;
margin: 0px 0px;
padding: 0px;
top: 0px;
bottom: 0px;
left: 0px;
right: 0px;
}
.obj_properties .backform-tab > .tab-content {
padding: 0px;
overflow-y: auto;
background-color: $color-gray-light;
}
.obj_properties {
padding: 0px;
}
.obj_properties .pgadmin-control .uneditable-input {
border: 0px !important;
-webkit-box-shadow: none !important;
box-shadow: none !important;
-webkit-transition: none !important;
-o-transition: none !important;
transition: none !important;
background-color: transparent !important;
height: 20px;
padding: 0px;
margin-top: 2px;
vertical-align: middle;
height: 100%;
width: 100%;
background-color: $color-gray-light;
}
/* Message panel shown on browser tabs */
.pg-panel-message {
width: 80%;
margin: 0 auto;
margin-top: 25px !important;
padding-top: 25px !important;
position: relative;
text-align: center;
font-size: $font-size-base;
@ -330,78 +303,6 @@
width: 100%;
}
.obj_properties fieldset > div > .pgadmin-control-group > label {
min-height: 28px;
}
.obj_properties fieldset > .fieldset-content {
padding: 5px 10px;
}
.obj_properties .accordian-group > .accordian-content {
padding: 5px 10px;
}
.obj_properties .badge {
display: block;
text-align: left;
cursor: pointer;
background-color: $badge-header-bg;
padding: 7px;
font-size: inherit;
border-bottom: $panel-border;
border-radius: 0rem;
border-top-left-radius: $card-border-radius;
border-top-right-radius: $card-border-radius;
&.collapsed {
border-bottom: none !important;
border-radius: $card-border-radius;
}
}
.obj_properties .badge .caret {
display: inline-block;
margin-left: 2px;
margin-right: 4px;
width: 0.7rem;
}
.obj_properties .badge .caret::before {
font-family: $font-family-icon;
content: "\f078";
font-size: 0.7rem;
margin-left: 0rem;
font-weight: 900;
}
.obj_properties .collapsed .caret::before {
font-family: $font-family-icon;
content: "\f054";
font-size: 0.7rem;
border: none;
font-weight: 900;
}
.obj_properties table td {
vertical-align: top;
}
.obj_properties .set-group {
margin: 0.5rem 0rem;
padding: 0rem;
}
.obj_properties .accordian-group {
margin: 0.5rem 0rem;
padding: 0rem;
border: $panel-border;
border-radius: $card-border-radius;
background-color: $color-bg;
fieldset.inline-fieldset {
background: $color-bg;
}
}
fieldset.inline-fieldset {
padding: 10px;
border-radius: $card-border-radius;
@ -797,6 +698,7 @@ body {
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
font-size: 0.875rem;
}
/* Security label's label column font size */
@ -823,10 +725,6 @@ body {
font-weight: 900;
}
.pg-el-container {
background-color: $negative-bg;
}
.nav-tabs {
background-color: $header-bg;
}

View File

@ -1,127 +0,0 @@
.select2-dropdown {
background-color: $input-bg;
color: $input-color;
}
.select2-container--default .select2-results__option[aria-selected=true] {
background-color: $select2-container-bg-selected;
color: $select2-container-fg-selected;
}
.select2-container--default .select2-results__option--highlighted {
background-color: $select2-container-hover-bg !important;
color: $select2-container-hover-fg !important;
}
.select2-container--default .select2-selection--multiple {
background-color: $input-bg;
color: $input-color;
}
.select2-container--default .select2-selection--multiple .select2-selection__choice {
background-color: $tree-bg-selected;
color: $tree-fg-selected;
border: $input-border-width solid $dropdown-link-hover-bg;
line-height: 2;
& .select2-selection__choice__remove {
color: $dropdown-link-remove-color;
margin-right: 0.25rem;
}
}
.select2-container--default .select2-search--inline .select2-search__field {
background: transparent none repeat scroll 0% 0%;
border: medium none;
outline: 0px none;
box-shadow: none;
width: 100% !important;
}
.select2-container--default .select2-search__field {
background-color: $input-bg;
color: $input-color;
}
.renderable > .select2-container {
width: 100% !important;
}
.select2-container .select2-selection--single {
height: auto;
min-height: 28px;
background-color: $input-bg;
& .select2-selection__rendered{
line-height: inherit;
padding: $input-padding-y $input-padding-x;
padding-right: 1.5rem;
color: $input-color;
}
}
.select2-container--default .select2-selection--single .select2-selection__arrow {
top: 0px;
height: 100%;
}
.select2-container--default.select2-container--focus {
& .select2-selection--single,
& .select2-selection--multiple {
border-color: $input-focus-border-color !important;
outline: 0;
-webkit-box-shadow: $input-focus-box-shadow;
box-shadow: $input-focus-box-shadow;
}
}
.select2-results span.wcTabIcon {
padding-left: 20px;
}
.select2-selection {
color: $input-color;
background-color: $input-bg;
background-clip: padding-box;
border: $input-border-width solid $input-border-color !important;
}
.select2-container--default.select2-container--disabled .select2-selection--multiple {
background-color: $input-disabled-bg !important;
opacity: 1;
color: $text-muted;
}
.select2-container--default.select2-container--disabled .select2-selection--single {
background-color: $input-disabled-bg !important;
opacity: 1;
color: $text-muted;
}
.select2-container--default.select2-container--disabled .select2-selection__rendered {
color: $text-muted;
}
.select2-select-all-adapter-container {
padding: 3px 0px;
background-color: $color-primary;
margin-bottom: 3px;
}
/* select2 readonly */
select[readonly].select2-hidden-accessible + .select2-container {
pointer-events: none;
touch-action: none;
}
select[readonly].select2-hidden-accessible + .select2-container .select2-selection {
background: $select2-readonly;
color: $text-muted;
box-shadow: none;
}
select[readonly].select2-hidden-accessible + .select2-container .select2-selection__arrow, select[readonly].select2-hidden-accessible + .select2-container .select2-selection__clear {
display: none;
}

View File

@ -1,174 +0,0 @@
.tree-icon-right:before {
font-family: $font-family-icon;
content: "\f054" !important;
right: 15px;
top: 3px;
font-size: 0.6rem;
line-height: 2;
border-style: none;
font-weight: 900;
}
.aciTree, .aciTree.aciTreeFullRow {
& .aciTreeButton, & .aciTreePush, & .aciTreeItem, & .aciTreeIcon, & .aciTreeText, & .aciTreeColumn {
color: $tree-text-fg;
}
.aciTreeLi {
display: grid !important;
cursor: pointer;
}
.aciTreeText {
font-family: $font-family-primary !important;
font-size: $tree-font-size !important;
}
.aciTreeUl {
list-style: none;
margin: 0;
padding: 0;
}
.aciTreeLine {
margin: unset !important;
border: unset !important;
}
.aciTreeSelected > .aciTreeLine {
background: unset !important;
background-color: $tree-bg-selected !important;
border-color: $color-primary-light;
border-right: $active-border !important;
border-left: none !important;
border-top: none !important;
border-bottom: none !important;
-webkit-border-radius: none !important;
-moz-border-radius: none !important;
border-radius: none !important;
& .aciTreeItem {
background-color: $tree-bg-selected;
border: 1px solid transparent;
-webkit-border-radius: none !important;
-moz-border-radius: none !important;
border-radius: none !important;
color: $tree-fg-selected;
}
& .aciTreeText {
color: $tree-text-hover-fg;
}
& .aciTreePush {
color: $tree-text-hover-fg;
}
}
.aciTreeItem {
white-space: nowrap !important;
}
&.aciTreeLoad {
background: none;
}
.aciTreeLine.aciTreeHover {
background: unset !important;
background-color: $tree-bg-hover !important;
-webkit-border-radius: none !important;
-moz-border-radius: none !important;
border-radius: none !important;
& .aciTreeItem {
background-color: inherit;
border: 1px solid transparent;
-webkit-border-radius: none !important;
-moz-border-radius: none !important;
border-radius: none !important;
color: $tree-fg-hover;
}
& .aciTreeText {
color: $tree-text-hover-fg;
}
& .aciTreePush {
color: $tree-text-hover-fg;
}
}
&.aciTreeFocus {
& .aciTreeFocus > .aciTreeLine {
background-color: $tree-bg-selected !important;
border-right: $active-border !important;
}
& .aciTreeSelected >.aciTreeLine .aciTreeItem {
background-color: $tree-bg-selected;
}
& .aciTreeFocus >.aciTreeLine .aciTreeItem,
& .aciTreeSelected.aciTreeFocus >.aciTreeLine .aciTreeItem {
border: 1px solid transparent;
color: $tree-fg-selected;
}
}
.aciTreeButton {
background: none;
}
.aciTreePush {
background: none;
text-align: center;
vertical-align: middle;
font-size: 0.85em;
}
.aciTreeEntry, .aciTreeBranch, &[dir=rtl] .aciTreeBranch {
overflow:hidden;
background: none !important;
}
.aciTreeInode>.aciTreeLine .aciTreePush {
&:before,
&.aciTreeHover:before {
background-position: 6px center !important;
font-family: $font-family-icon;
content: "\f054" !important;
border-style: none;
margin-left: 5px;
font-weight: 900;
}
}
.aciTreeLoad>.aciTreeLine .aciTreePush {
&:before,
&.aciTreeHover:before {
content: " " !important;
font-weight: 900;
}
}
.aciTreeOpen >.aciTreeLine .aciTreePush {
&:before,
&.aciTreeHover:before {
background-position: -14px center !important;
font-family: $font-family-icon;
content: "\f078" !important;
border-style: none;
margin-left: 5px;
font-weight: 900;
}
}
.aciTreePush>span {
width: 15px;
height: 15px;
left: 2px;
background: $loader-icon-small 0 0 no-repeat;
background-color: inherit!important;
}
}

View File

@ -40,7 +40,6 @@
}
}
/* darken % taken from bootstrap - button_variant */
.wcFrameButton:hover, .wcFrameButtonHover, .wcFrameButton:focus {
background-color: $btn-frame-close-bg;
}

View File

@ -20,13 +20,8 @@ $theme-colors: (
@import "bootstrap/scss/bootstrap";
@import 'webcabin.pgadmin';
@import 'bootstrap.overrides';
@import 'tree.overrides';
@import 'select2.overrides';
@import 'codemirror.overrides';
@import 'alert';
@import 'pgadmin.grid';
@import 'pgadmin.style';
@import 'bootstrap4-toggle.overrides';
@import 'jsoneditor.overrides';
@import 'rc-dock/dist/rc-dock.css';
@import '@szhsin/react-menu/dist/index.css';

View File

@ -327,17 +327,6 @@ $schemadiff-source-row-color: #ffebee !default;
$schemadiff-target-row-color: #fbe3bf !default;
$schema-diff-color-fg: $input-color !default;
/* Custom controls bootstrap changes */
$custom-forms-transition: none, none, none;
$custom-control-indicator-focus-border-color: $input-focus-border-color !default;
$custom-control-indicator-border-color: $input-border-color !default;
$select2-container-hover-bg: $tree-bg-hover !default;
$select2-container-hover-fg: $tree-fg-hover !default;
$select2-container-bg-selected: $tree-bg-selected !default;
$select2-container-fg-selected: $tree-fg-selected !default;
$select2-placeholder: #575757 !default;
$btn-primary-icon-bg: $color-bg !default;
$btn-primary-icon-fg: $color-fg !default;
$btn-primary-icon-hover-fg: $color-fg !default;
@ -372,11 +361,13 @@ $login-page-background: $color-primary !default;
}
$erd-bg-grid: url("data:image/svg+xml, %3Csvg width='100%25' viewBox='0 0 45 45' style='background-color:#{url-friendly-colour($erd-canvas-bg)}' height='100%25' xmlns='http://www.w3.org/2000/svg'%3E%3Cdefs%3E%3Cpattern id='smallGrid' width='15' height='15' patternUnits='userSpaceOnUse'%3E%3Cpath d='M 15 0 L 0 0 0 15' fill='none' stroke='#{url-friendly-colour($erd-canvas-grid)}' stroke-width='0.5'/%3E%3C/pattern%3E%3Cpattern id='grid' width='45' height='45' patternUnits='userSpaceOnUse'%3E%3Crect width='100' height='100' fill='url(%23smallGrid)'/%3E%3Cpath d='M 100 0 L 0 0 0 100' fill='none' stroke='#{url-friendly-colour($erd-canvas-grid)}' stroke-width='1'/%3E%3C/pattern%3E%3C/defs%3E%3Crect width='100%25' height='100%25' fill='url(%23grid)' /%3E%3C/svg%3E%0A");
$select2-readonly: $color-gray-lighter !default;
// psql tool variables
$psql-background: $color-bg !default;
$psql-foreground: $color-fg !default;
$psql-cursor: $color-fg !default;
$psql-cursorAccent: $color-fg !default;
$psql-selection: #326690 !default;
/* After removing bootstrap */
$dropdown-border-radius: 4px;

View File

@ -126,8 +126,6 @@ $color-success-hover-fg: $color-fg;
$datagrid-selected-color: $color-primary-fg;
$select2-placeholder: #999;
$span-text-color: #9D9FA1 !default;
$span-text-color-hover: $white !default;
$quick-search-a-text-color: $white !default;
@ -141,8 +139,6 @@ $erd-canvas-grid: #444952;
$erd-link-color: $color-fg;
$erd-link-selected-color: $color-fg;
$select2-readonly: $color-bg;
// psql tool variables
$psql-background: $color-bg;
$psql-foreground: $color-fg;

View File

@ -137,12 +137,6 @@ $tree-bg-hover: $color-fg;
$tree-fg-selected: $color-fg;
$tree-bg-selected: $color-primary-light;
$select2-container-hover-bg: $color-primary;
$select2-container-hover-fg: $color-bg;
$select2-container-bg-selected: $color-fg;
$select2-container-fg-selected: $color-bg;
$select2-placeholder: #999;
$sql-hint-active-fg: $color-bg;
$btn-primary-hover-bg: $color-fg;
@ -181,9 +175,6 @@ $card-header-border-color: $card-header-bg;
$card-border-color: transparent;
$card-bg: $color-gray;
$custom-control-indicator-focus-border-color: #FFFFFF !important;
$custom-control-indicator-border-color: $color-gray-lighter;
$panel-color-fg: $color-ternary;
$panel-border-color: $color-gray;

View File

@ -7,7 +7,6 @@
//
//////////////////////////////////////////////////////////////
import $ from 'jquery';
import _ from 'lodash';
import React from 'react';
import ReactDOM from 'react-dom';
@ -613,7 +612,7 @@ export default class DebuggerModule {
let closeUrl = url_for('debugger.close', {
'trans_id': res.data.data.debuggerTransId,
});
$.ajax({
self.api({
url: closeUrl,
method: 'DELETE',
});

View File

@ -18,7 +18,6 @@ import ERDTool from './erd_tool/components/ERDTool';
import ModalProvider from '../../../../static/js/helpers/ModalProvider';
import Theme from '../../../../static/js/Theme';
import { openNewWindow } from '../../../../static/js/utils';
import $ from 'jquery';
const wcDocker = window.wcDocker;
@ -149,23 +148,23 @@ export default class ERDModule {
registerDetachEvent(erdToolPanel);
let openErdToolURL = function(j) {
// add spinner element
let $spinner_el =
$(`<div class="pg-sp-container">
<div class="pg-sp-content">
<div class="row">
<div class="col-12 pg-sp-icon"></div>
</div>
</div>
</div>`).appendTo($(j).data('embeddedFrame').$container);
const frame = j.frameData.embeddedFrame;
const spinner = document.createElement('div');
spinner.setAttribute('class', 'pg-sp-container');
spinner.innerHTML = `
<div class="pg-sp-content">
<div class="pg-sp-icon"></div>
</div>
`;
frame.$container[0].appendChild(spinner);
let init_poller_id = setInterval(function() {
let frameInitialized = $(j).data('frameInitialized');
if (frameInitialized) {
if (j.frameData.frameInitialized) {
clearInterval(init_poller_id);
let frame = $(j).data('embeddedFrame');
if (frame) {
frame.onLoaded(()=>{
$spinner_el.remove();
spinner.remove();
});
frame.openHTML(erdToolForm);
}

View File

@ -9,14 +9,13 @@
import gettext from 'sources/gettext';
import url_for from 'sources/url_for';
import $ from 'jquery';
import _ from 'lodash';
import pgAdmin from 'sources/pgadmin';
import pgBrowser from 'top/browser/static/js/browser';
import * as csrfToken from 'sources/csrf';
import {initialize} from './psql_module';
let pgBrowserOut = initialize(gettext, url_for, $, _, pgAdmin, csrfToken, pgBrowser);
let pgBrowserOut = initialize(gettext, url_for, _, pgAdmin, csrfToken, pgBrowser);
module.exports = {
pgBrowser: pgBrowserOut,

View File

@ -28,7 +28,7 @@ export function setPanelTitle(psqlToolPanel, panelTitle) {
let wcDocker = window.wcDocker;
export function initialize(gettext, url_for, $, _, pgAdmin, csrfToken, Browser) {
export function initialize(gettext, url_for, _, pgAdmin, csrfToken, Browser) {
let pgBrowser = Browser;
let terminal = Terminal;
let parentData = null;
@ -184,23 +184,23 @@ export function initialize(gettext, url_for, $, _, pgAdmin, csrfToken, Browser)
let openPSQLToolURL = function(j) {
// add spinner element
let $spinner_el =
$(`<div class="pg-sp-container">
<div class="pg-sp-content">
<div class="row">
<div class="col-12 pg-sp-icon"></div>
</div>
</div>
</div>`).appendTo($(j).data('embeddedFrame').$container);
const frame = j.frameData.embeddedFrame;
const spinner = document.createElement('div');
spinner.setAttribute('class', 'pg-sp-container');
spinner.innerHTML = `
<div class="pg-sp-content">
<div class="pg-sp-icon"></div>
</div>
`;
frame.$container[0].appendChild(spinner);
let init_poller_id = setInterval(function() {
let frameInitialized = $(j).data('frameInitialized');
if (frameInitialized) {
if (j.frameData.frameInitialized) {
clearInterval(init_poller_id);
let frame = $(j).data('embeddedFrame');
if (frame) {
frame.onLoaded(()=>{
$spinner_el.remove();
spinner.remove();
});
frame.openHTML(psqlToolForm);
}

View File

@ -12,7 +12,6 @@ import * as showQueryTool from './show_query_tool';
import * as toolBar from 'pgadmin.browser.toolbar';
import * as panelTitleFunc from './sqleditor_title';
import * as commonUtils from 'sources/utils';
import $ from 'jquery';
import _ from 'lodash';
import pgWindow from 'sources/window';
import pgAdmin from 'sources/pgadmin';
@ -282,23 +281,22 @@ export default class SQLEditor {
let openQueryToolURL = function(j) {
// add spinner element
let $spinner_el =
$(`<div class="pg-sp-container">
<div class="pg-sp-content">
<div class="row">
<div class="col-12 pg-sp-icon"></div>
</div>
</div>
</div>`).appendTo($(j).data('embeddedFrame').$container);
const frame = j.frameData.embeddedFrame;
const spinner = document.createElement('div');
spinner.setAttribute('class', 'pg-sp-container');
spinner.innerHTML = `
<div class="pg-sp-content">
<div class="pg-sp-icon"></div>
</div>
`;
frame.$container[0].appendChild(spinner);
let init_poller_id = setInterval(function() {
let frameInitialized = $(j).data('frameInitialized');
if (frameInitialized) {
if (j.frameData.frameInitialized) {
clearInterval(init_poller_id);
let frame = $(j).data('embeddedFrame');
if (frame) {
frame.onLoaded(()=>{
$spinner_el.remove();
spinner.remove();
});
frame.openHTML(queryToolForm);
}

View File

@ -11,7 +11,6 @@ import gettext from '../../../../static/js/gettext';
import url_for from '../../../../static/js/url_for';
import {getPanelTitle} from './sqleditor_title';
import {getRandomInt} from 'sources/utils';
import $ from 'jquery';
import Notify from '../../../../static/js/helpers/Notifier';
function hasDatabaseInformation(parentData) {
@ -130,9 +129,9 @@ export function _set_dynamic_tab(pgBrowser, value){
let sqleditor_panels = pgBrowser.docker.findPanels('frm_sqleditor');
const process = panel => {
if(value) {
$('#' + panel.$title.index() + ' div:first').addClass('wcPanelTab-dynamic');
document.querySelector(`.wcPanelTab[id="${panel.$title.index()}"] div`).classList.add('wcPanelTab-dynamic');
} else {
$('#' + panel.$title.index() + ' div:first').removeClass('wcPanelTab-dynamic');
document.querySelector(`.wcPanelTab[id="${panel.$title.index()}"] div`).classList.remove('wcPanelTab-dynamic');
}
};
sqleditor_panels.forEach(process);

View File

@ -8,7 +8,7 @@
//////////////////////////////////////////////////////////////
import {pgBrowser} from 'pgadmin.browser.preferences';
import $ from 'jquery';
import EventBus from '../../../pgadmin/static/js/helpers/EventBus';
let dummy_cache = [
{
@ -44,6 +44,7 @@ describe('preferences related functions test', function() {
describe('get preference data related functions', function(){
beforeEach(function(){
pgBrowser.preferences_cache = dummy_cache;
pgBrowser.Events = new EventBus();
});
it('generate_preference_version', function() {
@ -101,61 +102,13 @@ describe('preferences related functions test', function() {
});
});
it('reflectPreferences', function() {
let editorOptions = {
'tabSize':2,
'lineWrapping':false,
'autoCloseBrackets':true,
'matchBrackets':true,
};
pgBrowser.preferences_cache.push({
id: 4, mid: 3, module:'sqleditor', name:'sql_font_size', value: 1.456,
});
pgBrowser.preferences_cache.push({
id: 4, mid: 3, module:'sqleditor', name:'tab_size', value: editorOptions.tabSize,
});
pgBrowser.preferences_cache.push({
id: 4, mid: 3, module:'sqleditor', name:'wrap_code', value: editorOptions.lineWrapping,
});
pgBrowser.preferences_cache.push({
id: 4, mid: 3, module:'sqleditor', name:'insert_pair_brackets', value: editorOptions.autoCloseBrackets,
});
pgBrowser.preferences_cache.push({
id: 4, mid: 3, module:'sqleditor', name:'brace_matching', value: editorOptions.matchBrackets,
});
/* Spies */
pgBrowser.editor = jasmine.createSpyObj(
'CodeMirror', ['setOption','refresh','getWrapperElement']
);
spyOn($.fn, 'css');
/* Call */
pgBrowser.reflectPreferences();
/* Tests */
expect(pgBrowser.editor.getWrapperElement).toHaveBeenCalled();
let setOptionCalls = pgBrowser.editor.setOption.calls;
expect(setOptionCalls.count()).toEqual(Object.keys(editorOptions).length);
for(let i = 0; i < Object.keys(editorOptions).length; i++) {
let option = Object.keys(editorOptions)[i];
expect(setOptionCalls.argsFor(i)).toEqual([option, editorOptions[option]]);
}
expect(pgBrowser.editor.refresh).toHaveBeenCalled();
});
it('onPreferencesChange', function() {
window.parent.$ = $;
spyOn($.fn, 'on');
spyOn(pgBrowser.Events, 'on');
let eventHandler = jasmine.createSpy('eventHandler');
pgBrowser.onPreferencesChange('somemodule', eventHandler);
if($.fn.on.calls.mostRecent()) {
expect($.fn.on.calls.mostRecent().args[0]).toEqual('prefchange:somemodule');
if(pgBrowser.Events.on.calls.mostRecent()) {
expect(pgBrowser.Events.on.calls.mostRecent().args[0]).toEqual('prefchange:somemodule');
}
});
});

View File

@ -11,40 +11,6 @@ import * as keyboardShortcuts from 'sources/keyboard_shortcuts';
import $ from 'jquery';
describe('the keyboard shortcuts', () => {
const F1_KEY = 112;
let debuggerElementSpy, event, debuggerUserShortcutSpy;
debuggerUserShortcutSpy = jasmine.createSpyObj(
'userDefinedShortcuts', [
{ 'edit_grid_keys': null },
{ 'next_panel_keys': null },
{ 'previous_panel_keys': null },
]
);
beforeEach(() => {
event = {
shift: false,
which: undefined,
preventDefault: jasmine.createSpy('preventDefault'),
cancelBubble: false,
stopPropagation: jasmine.createSpy('stopPropagation'),
stopImmediatePropagation: jasmine.createSpy('stopImmediatePropagation'),
};
});
describe('when the key is not handled by the function', function () {
beforeEach(() => {
event.which = F1_KEY;
keyboardShortcuts.processEventDebugger(
debuggerElementSpy, event, debuggerUserShortcutSpy
);
});
it('should allow event to propagate', () => {
expect(event.preventDefault).not.toHaveBeenCalled();
});
});
describe('when user wants to goto next panel', function () {
let dockerSpy = {
'_focusFrame': {

View File

@ -6,6 +6,7 @@ import { DATA_POINT_SIZE } from 'sources/chartjs';
import Graphs, {GraphsWrapper, transformData,
getStatsUrl, statsReducer} from '../../../pgadmin/dashboard/static/js/Graphs';
import { withTheme } from '../fake_theme';
describe('Graphs.js', ()=>{
it('transformData', ()=>{
@ -93,6 +94,7 @@ describe('Graphs.js', ()=>{
let graphComp = null;
let sid = 1;
let did = 1;
let ThemedGraphs = withTheme(Graphs);
beforeEach(()=>{
jasmineEnzyme();
let dashboardPref = {
@ -107,7 +109,7 @@ describe('Graphs.js', ()=>{
graph_line_border_width: 2
};
graphComp = mount(<Graphs preferences={dashboardPref} sid={sid} did={did} enablePoll={false} pageVisible={true} isTest={true} />);
graphComp = mount(<ThemedGraphs preferences={dashboardPref} sid={sid} did={did} enablePoll={false} pageVisible={true} isTest={true} />);
});
it('GraphsWrapper is rendered', (done)=>{
@ -118,7 +120,6 @@ describe('Graphs.js', ()=>{
it('pollDelay is set', (done)=>{
let found = graphComp.find('[data-testid="graph-poll-delay"]');
expect(found).toHaveClassName('d-none');
expect(found).toHaveText('1000');
done();
});
@ -136,9 +137,12 @@ describe('Graphs.js', ()=>{
graph_line_border_width: 2
};
graphComp.setProps({preferences: dashboardPref});
let found = graphComp.find('[data-testid="graph-poll-delay"]');
expect(found).toHaveText('5000');
done();
setTimeout(()=>{
graphComp.update();
let found = graphComp.find('[data-testid="graph-poll-delay"]');
expect(found).toHaveText('5000');
done();
}, 500);
});
});
});

View File

@ -4,6 +4,7 @@ import {mount} from 'enzyme';
import '../helper/enzyme.helper';
import {GraphsWrapper, X_AXIS_LENGTH, POINT_SIZE} from '../../../pgadmin/dashboard/static/js/Graphs';
import { withTheme } from '../fake_theme';
describe('<GraphsWrapper /> component', ()=>{
let graphComp = null;
@ -24,29 +25,32 @@ describe('<GraphsWrapper /> component', ()=>{
}],
refreshRate: 1,
};
let ThemedGraphsWrapper = withTheme(GraphsWrapper);
beforeEach(()=>{
jasmineEnzyme();
graphComp = mount(<GraphsWrapper sessionStats={defaultStats}
tpsStats={defaultStats}
tiStats={defaultStats}
toStats={defaultStats}
bioStats={defaultStats}
errorMsg={null}
showTooltip={true}
showDataPoints={true}
lineBorderWidth={2}
isDatabase={false}
isTest={true} />);
graphComp = mount(
<ThemedGraphsWrapper sessionStats={defaultStats}
tpsStats={defaultStats}
tiStats={defaultStats}
toStats={defaultStats}
bioStats={defaultStats}
errorMsg={null}
showTooltip={true}
showDataPoints={true}
lineBorderWidth={2}
isDatabase={false}
isTest={true} />
);
});
it('graph containers are rendered', (done)=>{
let found = graphComp.find('.card.dashboard-graph');
let found = graphComp.find('ChartContainer');
expect(found.length).toBe(5);
done();
});
it('graph headers are correct', (done)=>{
let found = graphComp.find('.card.dashboard-graph');
let found = graphComp.find('ChartContainer');
expect(found.at(0)).toIncludeText('Server sessions');
expect(found.at(1)).toIncludeText('Transactions per second');
expect(found.at(2)).toIncludeText('Tuples in');
@ -56,7 +60,7 @@ describe('<GraphsWrapper /> component', ()=>{
});
it('graph headers when database', (done)=>{
let found = graphComp.find('.card.dashboard-graph');
let found = graphComp.find('ChartContainer');
graphComp.setProps({isDatabase: true});
expect(found.at(0)).toIncludeText('Database sessions');
done();
@ -64,14 +68,15 @@ describe('<GraphsWrapper /> component', ()=>{
it('graph body shows the error', (done)=>{
graphComp.setProps({errorMsg: 'Some error occurred'});
let found = graphComp.find('.card.dashboard-graph .dashboard-graph-body');
found = graphComp.find('.card.dashboard-graph .dashboard-graph-body .pg-panel-error.pg-panel-message');
expect(found.at(0)).toIncludeText('Some error occurred');
expect(found.at(1)).toIncludeText('Some error occurred');
expect(found.at(2)).toIncludeText('Some error occurred');
expect(found.at(3)).toIncludeText('Some error occurred');
expect(found.at(4)).toIncludeText('Some error occurred');
done();
setTimeout(()=>{
graphComp.update();
let found = graphComp.find('ChartContainer');
expect(found.at(0)).toIncludeText('Some error occurred');
expect(found.at(1)).toIncludeText('Some error occurred');
expect(found.at(2)).toIncludeText('Some error occurred');
expect(found.at(3)).toIncludeText('Some error occurred');
expect(found.at(4)).toIncludeText('Some error occurred');
done();
}, 500);
});
});

View File

@ -9,7 +9,7 @@
import $ from 'jquery';
window.jQuery = window.$ = $;
import 'bootstrap';
import 'wcdocker';
import '../helper/enzyme.helper';

View File

@ -1,206 +0,0 @@
//////////////////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2023, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////////////////
import dialogTabNavigator from 'sources/dialog_tab_navigator';
import $ from 'jquery';
import 'bootstrap';
describe('dialogTabNavigator', function () {
let dialog, tabNavigator, backward_shortcut, forward_shortcut, fakeEvent;
beforeEach(() => {
dialog = $('<div tabindex="1" class="backform-tab" role="tabpanel">'+
' <ul class="nav nav-tabs" role="tablist">'+
' <li role="presentation">'+
' <a class="active" data-toggle="tab" tabindex="-1" data-tab-index="1" href="#1" aria-controls="1"> General</a>'+
' </li>'+
' <li role="presentation">'+
' <a data-toggle="tab" tabindex="-1" data-tab-index="5" href="#2" aria-controls="2"> Default Privileges</a>'+
' </li>'+
' <li role="presentation">'+
' <a data-toggle="tab" tabindex="-1" data-tab-index="6" href="#3" aria-controls="3"> SQL</a>'+
' </li>'+
' </ul>'+
' <ul class="tab-content">'+
' <div role="tabpanel" tabindex="-1" class="tab-pane fade collapse in active" id="1">'+
' </div>'+
' <div role="tabpanel" tabindex="-1" class="tab-pane fade collapse" id="2">'+
' <div class="inline-tab-panel" role="tabpanel">'+
' <ul class="nav nav-tabs" role="tablist">'+
' <li role="presentation" class="active">'+
' <a data-toggle="tab" tabindex="-1" data-tab-index="601" href="#11" aria-controls="11"> Tables</a>'+
' </li>'+
' <li role="presentation">'+
' <a data-toggle="tab" tabindex="-1" data-tab-index="602" href="#22" aria-controls="22"> Sequences</a>'+
' </li>'+
' </ul>'+
' <ul class="tab-content">'+
' <div role="tabpanel" tabindex="-1" class="tab-pane fade collapse in active" id="11" >'+
' </div>'+
' <div role="tabpanel" tabindex="-1" class="tab-pane fade collapse" id="22">'+
' </div>'+
' </ul>'+
' </div>'+
' </div>'+
' <div role="tabpanel" tabindex="-1" class="tab-pane fade collapse" id="3">'+
' </div>'+
' </ul>'+
'</div>');
backward_shortcut = {
'alt': false,
'shift': true,
'control': true,
'key': {'key_code': 91, 'char': '['},
};
forward_shortcut = {
'alt': false,
'shift': true,
'control': true,
'key': {'key_code': 93, 'char': ']'},
};
tabNavigator = new dialogTabNavigator.dialogTabNavigator(
dialog, backward_shortcut, forward_shortcut);
fakeEvent = { stopPropagation: () => true };
});
describe('navigate', function () {
beforeEach(() => {
spyOn(tabNavigator, 'navigateBackward').and.callThrough();
spyOn(tabNavigator, 'navigateForward').and.callThrough();
});
it('navigate backward', function () {
tabNavigator.onKeyboardEvent(fakeEvent, 'shift+ctrl+[');
expect(tabNavigator.navigateBackward).toHaveBeenCalled();
expect(tabNavigator.navigateForward).not.toHaveBeenCalled();
});
it('navigate forward', function () {
tabNavigator.onKeyboardEvent(fakeEvent, 'shift+ctrl+]');
expect(tabNavigator.navigateForward).toHaveBeenCalled();
expect(tabNavigator.navigateBackward).not.toHaveBeenCalled();
});
it('should not navigate', function () {
tabNavigator.onKeyboardEvent(fakeEvent, 'shift+ctrl+a');
expect(tabNavigator.navigateForward).not.toHaveBeenCalled();
expect(tabNavigator.navigateBackward).not.toHaveBeenCalled();
});
});
describe('navigateForward from fist tab to second tab', function () {
let navigateForwardResult;
beforeEach(() => {
spyOn(tabNavigator, 'navigateForward').and.callThrough();
navigateForwardResult = tabNavigator.navigateForward(
dialog.find('ul.nav-tabs:first'),
dialog.find('div#1'),
fakeEvent
);
});
it('should return true', function () {
expect(navigateForwardResult).toEqual(true);
});
});
describe('navigateForward from last tab', function () {
let navigateForwardResult;
beforeEach(() => {
// set second tab active
dialog.find('ul.nav-tabs li a.active').removeClass('active');
dialog.find('ul.nav-tabs li a[href="#3"]').addClass('active');
spyOn(tabNavigator, 'navigateForward').and.callThrough();
navigateForwardResult = tabNavigator.navigateForward(
dialog.find('ul.nav-tabs:first'),
dialog.find('div#1'),
fakeEvent
);
});
it('should return false', function () {
expect(navigateForwardResult).toEqual(false);
});
});
describe('navigateBackward from second tab to first tab', function () {
let navigateBackwardResult;
beforeEach(() => {
// set second tab active
dialog.find('ul.nav-tabs li a.active').removeClass('active');
dialog.find('ul.nav-tabs li a[href="#2"]').addClass('active');
spyOn(tabNavigator, 'navigateBackward').and.callThrough();
navigateBackwardResult = tabNavigator.navigateBackward(
dialog.find('ul.nav-tabs:first'),
dialog.find('div#1'),
fakeEvent
);
});
it('should return true', function () {
expect(navigateBackwardResult).toEqual(true);
});
});
describe('navigateBackward from first tab', function () {
let navigateBackwardResult;
beforeEach(() => {
spyOn(tabNavigator, 'navigateBackward').and.callThrough();
navigateBackwardResult = tabNavigator.navigateBackward(
dialog.find('ul.nav-tabs:first'),
dialog.find('div#1'),
fakeEvent
);
});
it('should return false', function () {
expect(navigateBackwardResult).toEqual(false);
});
});
});

View File

@ -22,49 +22,6 @@ let webpackShimConfig = {
'bootstrap': {
'deps': ['jquery'],
},
'select2': {
'deps': ['jquery'],
'exports': '$.fn.select2',
},
'bootstrap.datepicker': {
'deps': ['jquery', 'bootstrap'],
'exports': 'jQuery.fn.datepicker',
},
'bootstrap.datetimepicker': {
'deps': ['moment'],
'exports': 'jQuery.fn.datetimepicker',
},
'bootstrap.toggle': {
deps: ['jquery', 'bootstrap'],
'exports': '$.fn.bootstrapToggle',
},
'jquery.event.drag': {
'deps': ['jquery'], 'exports': 'jQuery.fn.drag',
},
'jquery.ui': {'deps': ['jquery']},
'jqueryui.position': {
'deps': ['jquery'],
'exports': 'jQuery.ui.position',
},
'jquery.contextmenu': {
'deps': ['jquery', 'jqueryui.position'],
'exports': 'jQuery.contextMenu',
},
'jquery.aciplugin': {
'deps': ['jquery'],
'exports': 'aciPluginClass',
},
'jquery.acisortable': {
'deps': ['jquery', 'jquery.aciplugin'],
'exports': 'aciPluginClass.plugins.aciSortable',
},
'jquery.acifragment': {
'deps': ['jquery', 'jquery.aciplugin'],
'exports': 'aciPluginClass.plugins.aciFragment',
},
'wcdocker': {
'deps': ['jquery.contextmenu'],
},
},
// Map module id to file path used in 'define(['baseurl', 'misc']). It is
@ -82,10 +39,8 @@ let webpackShimConfig = {
'pgbrowser': path.join(__dirname, './pgadmin/browser/static/js/'),
// Vendor JS
'jquery': path.join(__dirname, './node_modules/jquery/dist/jquery'),
'wcdocker': path.join(__dirname, './node_modules/webcabin-docker/Build/wcDocker.min'),
'moment': path.join(__dirname, './node_modules/moment/moment'),
'jqueryui.position': path.join(__dirname, './node_modules/jquery-contextmenu/dist/jquery.ui.position'),
'jquery.contextmenu': path.join(__dirname, './node_modules/jquery-contextmenu/dist/jquery.contextMenu'),
'dropzone': path.join(__dirname, './node_modules/dropzone/dist/dropzone'),
'bignumber': path.join(__dirname, './node_modules/bignumber.js/bignumber'),
@ -112,10 +67,6 @@ let webpackShimConfig = {
//socket
'socketio': path.join(__dirname, './node_modules/socket.io-client/dist/socket.io.js'),
'bootstrap.datetimepicker': path.join(__dirname, './node_modules/tempusdominus-bootstrap-4/build/js/tempusdominus-bootstrap-4.min'),
'bootstrap.toggle': path.join(__dirname, './node_modules/bootstrap4-toggle/js/bootstrap4-toggle.min'),
'select2': path.join(__dirname, './node_modules/select2/dist/js/select2.full'),
'pgadmin.about': path.join(__dirname, './pgadmin/about/static/js/about'),
'pgadmin.authenticate.kerberos': path.join(__dirname, './pgadmin/authenticate/static/js/kerberos'),
'pgadmin.browser': path.join(__dirname, './pgadmin/browser/static/js/browser'),
@ -124,7 +75,6 @@ let webpackShimConfig = {
'pgadmin.browser.events': path.join(__dirname, './pgadmin/browser/static/js/events'),
'pgadmin.browser.endpoints': '/browser/js/endpoints',
'pgadmin.browser.constants': '/browser/js/constants',
'pgadmin.browser.error': path.join(__dirname, './pgadmin/browser/static/js/error'),
'pgadmin.browser.frame': path.join(__dirname, './pgadmin/browser/static/js/frame'),
'pgadmin.browser.keyboard': path.join(__dirname, './pgadmin/browser/static/js/keyboard'),
'pgadmin.browser.layout': path.join(__dirname, './pgadmin/browser/static/js/layout'),
@ -233,7 +183,6 @@ let webpackShimConfig = {
// Define list of pgAdmin common libraries to bundle them separately
// into commons JS from app.bundle.js
pgLibs: [
'pgadmin.browser.error',
'pgadmin.browser.collection',
'pgadmin.browser.events', 'pgadmin.browser.panel', 'pgadmin',
'pgadmin.browser.frame', 'pgadmin.browser',

View File

@ -124,8 +124,6 @@ module.exports = {
'wcdocker': path.join(__dirname, './node_modules/webcabin-docker/Build/wcDocker'),
'color-picker': path.join(__dirname, './node_modules/@simonwep/pickr/dist/pickr.min'),
'bignumber': path.join(__dirname, './node_modules/bignumber.js/bignumber'),
'bootstrap.datetimepicker': path.join(__dirname, './node_modules/tempusdominus-bootstrap-4/build/js/tempusdominus-bootstrap-4.min'),
'bootstrap.toggle': path.join(__dirname, './node_modules/bootstrap4-toggle/js/bootstrap4-toggle.min'),
'react': path.join(__dirname, 'node_modules/react'),
'react-dom': path.join(__dirname, 'node_modules/react-dom'),
'socketio': path.join(__dirname, './node_modules/socket.io-client/dist/socket.io.js'),

File diff suppressed because it is too large Load Diff