diff --git a/web/pgadmin/misc/static/explain/js/explain.js b/web/pgadmin/misc/static/explain/js/explain.js
index 0cf78abff..da595e6b3 100644
--- a/web/pgadmin/misc/static/explain/js/explain.js
+++ b/web/pgadmin/misc/static/explain/js/explain.js
@@ -753,6 +753,12 @@ define('pgadmin.misc.explain', [
return data;
},
+ getLabel: function() {
+ return this.get('Schema') == undefined ?
+ this.get('image_text') :
+ (this.get('Schema') + '.' + this.get('image_text'));
+ },
+
// Draw image, its name and its tooltip
draw: function(
s, xpos, ypos, pXpos, pYpos, graphContainer, toolTipContainer,
@@ -802,9 +808,7 @@ define('pgadmin.misc.explain', [
// Draw text below the node
- var node_label = this.get('Schema') == undefined ?
- this.get('image_text') :
- (this.get('Schema') + '.' + this.get('image_text'));
+ var node_label = this.getLabel();
g.multitext(
currentXpos + (pWIDTH / 2) + TXT_ALIGN,
currentYpos + pHEIGHT - TXT_ALIGN,
@@ -943,34 +947,29 @@ define('pgadmin.misc.explain', [
IMAGE_WIDTH,
IMAGE_HEIGHT
);
+ image.attr({style: 'cursor: pointer'});
// Draw tooltip
- var image_data = this.toJSON();
- var title = '
';
- _.each(image_data, function(value, key) {
- if (key !== 'image' && key !== 'Plans' &&
- key !== 'level' && key !== 'image' &&
- key !== 'image_text' && key !== 'xpos' &&
- key !== 'ypos' && key !== 'width' &&
- key !== 'height') {
- title += `${key}: ${value}\n`;
- }
- });
-
- title += '';
-
- image.append(Snap.parse(title));
-
- image.mouseover(() => {
+ var image_data = this.toJSON(),
+ nodeLabel = this.getLabel();
+ image.click(() => {
// Empty the tooltip content if it has any and add new data
- toolTipContainer.empty();
+ let toolTipBody = toolTipContainer.find('.details-body');
+ let toolTipTitle = toolTipContainer.find('.details-title');
+ toolTipTitle.text(nodeLabel);
+
+ toolTipBody.empty();
// Remove the title content so that we can show our custom build tooltips.
image.node.textContent = '';
- var tooltip = $('', {
- class: 'pgadmin-tooltip-table',
- }).appendTo(toolTipContainer);
+ var tooltipTable = $(`
+ `
+ ).appendTo(toolTipBody);
+ var tooltip = tooltipTable.find('tbody');
+
_.each(image_data, function(value, key) {
if (key !== 'image' && key !== 'Plans' &&
key !== 'level' && key !== 'image' &&
@@ -987,42 +986,8 @@ define('pgadmin.misc.explain', [
`);
}
});
-
- var zoomFactor = graphContainer.data('zoom-factor');
-
- // Calculate co-ordinates for tooltip
- var toolTipX = ((currentXpos + pWIDTH) * zoomFactor - graphContainer.scrollLeft());
- var toolTipY = ((currentYpos) * zoomFactor - graphContainer.scrollTop());
-
- toolTipX = toolTipX < 0 ? 0 : (toolTipX);
- toolTipY = toolTipY < 0 ? 0 : (toolTipY);
-
- toolTipX = toolTipX > graphContainer.width() - toolTipContainer[0].clientWidth ? toolTipX - (toolTipContainer[0].clientWidth+(pWIDTH* zoomFactor)) : toolTipX;
- toolTipY = toolTipY > graphContainer.height() - toolTipContainer[0].clientHeight ? graphContainer.height() - toolTipContainer[0].clientHeight : toolTipY;
-
- // Show toolTip at respective x,y coordinates
- toolTipContainer.css({
- 'opacity': '0.8',
- });
- toolTipContainer.css('left', toolTipX);
- toolTipContainer.css('top', toolTipY);
-
- $('.pgadmin-explain-tooltip').css('padding', '5px');
- $('.pgadmin-explain-tooltip').css('border', '1px solid white');
- });
-
- // Remove tooltip when mouse is out from node's area
- image.mouseout(() => {
- /* Append the title again which we have removed on mouse over event, so
- * that our custom tooltip should be visible.
- */
- image.append(Snap.parse(title));
- toolTipContainer.empty();
- toolTipContainer.css({
- 'opacity': '0',
- });
- toolTipContainer.css('left', 0);
- toolTipContainer.css('top', 0);
+ toolTipContainer.removeClass('d-none');
+ toolTipBody.scrollTop(0);
});
},
});
@@ -1362,16 +1327,23 @@ define('pgadmin.misc.explain', [
// Main div to be drawn all images on
var planDiv = $('', {
- class: 'pgadmin-explain-container w-100 h-100 overflow-auto',
- }).appendTo(graphicalContainer),
- // Div to draw tool-tip on
- toolTip = $('', {
- id: 'toolTip',
- class: 'pgadmin-explain-tooltip',
- }).appendTo(graphicalContainer);
- toolTip.empty();
+ class: 'pgadmin-explain-container w-100 h-100 overflow-auto',
+ }).appendTo(graphicalContainer);
planDiv.data('zoom-factor', curr_zoom_factor);
+ var explainDetails = $(
+ ``
+ ).appendTo(graphicalContainer);
+ explainDetails.find('.details-close').on('click', ()=>{
+ explainDetails.addClass('d-none');
+ });
+
var w = 0,
h = yMargin;
@@ -1420,7 +1392,7 @@ define('pgadmin.misc.explain', [
var s = Snap(w, h),
$svg = $(s.node).detach();
planDiv.append($svg);
- main_plan.draw(s, w - xMargin, yMargin, planDiv, toolTip, ctx);
+ main_plan.draw(s, w - xMargin, yMargin, planDiv, explainDetails, ctx);
var initPanelWidth = planDiv.width();
diff --git a/web/pgadmin/misc/static/explain/js/explain_statistics.js b/web/pgadmin/misc/static/explain/js/explain_statistics.js
index 6f4dd306d..b918fe98f 100644
--- a/web/pgadmin/misc/static/explain/js/explain_statistics.js
+++ b/web/pgadmin/misc/static/explain/js/explain_statistics.js
@@ -30,12 +30,15 @@ let StatisticsModel = Backbone.Model.extend({
$('.pg-explain-stats-area').removeClass('d-none');
}
- var tooltip = $('', {
- class: 'pgadmin-tooltip-table',
- });
+ var tooltipTable = $(`
+ `
+ );
+ var tooltip = tooltipTable.find('tbody');
if (Object.keys(jit_stats).length > 0){
- tooltip.append('| ' + gettext('JIT:') + ' |
');
+ tooltip.append('| ' + gettext('JIT:') + ' |
');
_.each(jit_stats, function(value, key) {
key = _.escape(key);
value = _.escape(value);
@@ -49,7 +52,7 @@ let StatisticsModel = Backbone.Model.extend({
}
if (Object.keys(triggers_stats).length > 0){
- tooltip.append('| ' + gettext('Triggers:') + ' |
');
+ tooltip.append('| ' + gettext('Triggers:') + ' |
');
_.each(triggers_stats, function(triggers, key_id) {
if (triggers instanceof Object) {
_.each(triggers, function(value, key) {
@@ -88,7 +91,7 @@ let StatisticsModel = Backbone.Model.extend({
}
if (Object.keys(summary).length > 0){
- tooltip.append('| ' + gettext('Summary:') + ' |
');
+ tooltip.append('| ' + gettext('Summary:') + ' |
');
_.each(summary, function(value, key) {
key = _.escape(key);
value = _.escape(value);
@@ -101,7 +104,7 @@ let StatisticsModel = Backbone.Model.extend({
});
}
- $('.pg-explain-stats-area').off('mouseover').on('mouseover', () => {
+ $('.pg-explain-stats-area').off('click').on('click', () => {
// Empty the tooltip content if it has any and add new data
if (Object.keys(jit_stats).length == 0 &&
@@ -110,30 +113,15 @@ let StatisticsModel = Backbone.Model.extend({
return;
}
- toolTipContainer.empty();
- toolTipContainer.append(tooltip);
+ let toolTipBody = toolTipContainer.find('.details-body');
+ let toolTipTitle = toolTipContainer.find('.details-title');
+ toolTipTitle.text('Statistics');
- // Show toolTip at respective x,y coordinates
- toolTipContainer.css({
- 'opacity': '0.8',
- 'left': '',
- 'right': '65px',
- 'top': '15px',
- });
+ toolTipBody.empty();
+ toolTipBody.append(tooltipTable);
- $('.pgadmin-explain-tooltip').css('padding', '5px');
- $('.pgadmin-explain-tooltip').css('border', '1px solid white');
- });
-
- // Remove tooltip when mouse is out from node's area
- $('.pg-explain-stats-area').off('mouseout').on('mouseout', () => {
- toolTipContainer.empty();
- toolTipContainer.css({
- 'opacity': '0',
- 'left': 0,
- 'top': 0,
- 'right': '',
- });
+ toolTipContainer.removeClass('d-none');
+ toolTipBody.scrollTop(0);
});
},
});
diff --git a/web/pgadmin/misc/static/explain/scss/_explain.scss b/web/pgadmin/misc/static/explain/scss/_explain.scss
index 095372ec5..458dca075 100644
--- a/web/pgadmin/misc/static/explain/scss/_explain.scss
+++ b/web/pgadmin/misc/static/explain/scss/_explain.scss
@@ -1,12 +1,29 @@
-.pgadmin-explain-tooltip {
+.pgadmin-explain-details {
+ min-width: 200px;
+ max-width: 300px;
position: absolute;
- opacity: 0;
- color: $popover-body-color;
- background-color: $popover-bg;
+ top: 0.25rem;
+ bottom: 0.25rem;
+ right: 0.25rem;
border-color: $popover-border-color;
box-shadow: $popover-box-shadow;
+ word-break: break-all;
+ display: flex;
+ flex-direction: column;
+ z-index: 99;
+
+ .details-header {
+ padding: 0.25rem;
+ font-weight: unset;
+ }
+
+ .details-body {
+ overflow: auto;
+ flex-grow: 1;
+ }
}
+
.sql-editor-explain {
.backform-tab {
.tab-content {
diff --git a/web/regression/javascript/misc/explain/explain_statistics_spec.js b/web/regression/javascript/misc/explain/explain_statistics_spec.js
index e33194bda..5ad146765 100644
--- a/web/regression/javascript/misc/explain/explain_statistics_spec.js
+++ b/web/regression/javascript/misc/explain/explain_statistics_spec.js
@@ -18,10 +18,14 @@ describe('ExplainStatistics', () => {
beforeEach(function() {
statsModel = new StatisticsModel();
statsDiv = '';
- tooltipContainer = $('', {
- id: 'toolTip',
- class: 'pgadmin-explain-tooltip',
- });
+ tooltipContainer = $(
+ ``
+ );
});
describe('No Statistics', () => {
@@ -49,20 +53,12 @@ describe('ExplainStatistics', () => {
expect($('.pg-explain-stats-area').hasClass('d-none')).toEqual(false);
});
- it('Mouse over event should be trigger', () => {
+ it('Mouse click event should be trigger', () => {
// Trigger mouse over event
- var hoverEvent = new $.Event('mouseover');
- $('.pg-explain-stats-area').trigger(hoverEvent);
+ var clickEvent = new $.Event('click');
+ $('.pg-explain-stats-area').trigger(clickEvent);
- expect(tooltipContainer.css('opacity')).toEqual('0.8');
- });
-
- it('Mouse out event should be trigger', () => {
- // Trigger mouse out event
- var hoverEvent = new $.Event('mouseout');
- $('.pg-explain-stats-area').trigger(hoverEvent);
-
- expect(tooltipContainer.css('opacity')).toEqual('0');
+ expect(tooltipContainer.hasClass('d-none')).toBe(false);
});
});
@@ -78,20 +74,12 @@ describe('ExplainStatistics', () => {
expect($('.pg-explain-stats-area').hasClass('d-none')).toEqual(false);
});
- it('Mouse over event should be trigger', () => {
+ it('Mouse click event should be trigger', () => {
// Trigger mouse over event
- var hoverEvent = new $.Event('mouseover');
- $('.pg-explain-stats-area').trigger(hoverEvent);
-
- expect(tooltipContainer.css('opacity')).toEqual('0.8');
- });
-
- it('Mouse out event should be trigger', () => {
- // Trigger mouse out event
- var hoverEvent = new $.Event('mouseout');
- $('.pg-explain-stats-area').trigger(hoverEvent);
+ var clickEvent = new $.Event('click');
+ $('.pg-explain-stats-area').trigger(clickEvent);
- expect(tooltipContainer.css('opacity')).toEqual('0');
+ expect(tooltipContainer.hasClass('d-none')).toBe(false);
});
});
@@ -111,20 +99,12 @@ describe('ExplainStatistics', () => {
expect($('.pg-explain-stats-area').hasClass('d-none')).toEqual(false);
});
- it('Mouse over event should be trigger', () => {
+ it('Mouse click event should be trigger', () => {
// Trigger mouse over event
- var hoverEvent = new $.Event('mouseover');
- $('.pg-explain-stats-area').trigger(hoverEvent);
-
- expect(tooltipContainer.css('opacity')).toEqual('0.8');
- });
-
- it('Mouse out event should be trigger', () => {
- // Trigger mouse out event
- var hoverEvent = new $.Event('mouseout');
- $('.pg-explain-stats-area').trigger(hoverEvent);
+ var clickEvent = new $.Event('click');
+ $('.pg-explain-stats-area').trigger(clickEvent);
- expect(tooltipContainer.css('opacity')).toEqual('0');
+ expect(tooltipContainer.hasClass('d-none')).toBe(false);
});
});
});