Forum Discussion

gwolfe's avatar
gwolfe
Data Pipeline
04-27-2023

Heat Map Formatting and Legend Bug

Hey! Does anyone know how to:
1. Know how to get rid of all the white space at the top of this widget?

2. Know how to widen the first column with the headers?

3. A work-around for the bug on the legend where it breaks anytime a filter is touched? 

Thanks in advance!

 

4 Replies

Replies have been turned off for this discussion
  • Hey gwolfe 

    We'd be happy to help where is this plugin/script from? If you send it over we can have one of our Sisense experts have a look.

    QBeeQ develop a wide range of advanced visualisations which can be found in our Advanced Data Viz PowerUp,

    This includes a Dynamic Heatmap which can be configured in a radial, semi-circular or flat view,

    Please do not hesitate to reach out for more information, always happy to help the Sisense eco-system

    [email protected]

    QBeeQ - Gold Sisense implementation & Development Partner

     

     

  • Hey gwolfe See my recommendations below, if you have any additional questions, please do not hesitate to reach out, we're always here to help

    [email protected]

    1. In the HCColorHeatmap.js file, there is margin array. The values are in this order [top, right, bottom, left]. If you set top value to at most 40 or less, it will free up some space from the top of the chart.
    2. In the HCColorHeatmap.js file, there is margin array. The values are in this order [top, right, bottom, left]. If you set left value to 100 or even 160, it will add space to the left side of the chart.
    3. In widget.js, if we wrap the DisplayColorHeatmap method inside setTimeout method for 1 sec or higher, it will fix the issue.

    setTimeout(() => { DisplayColorHeatmap ( widget, ChartDivName, svgWidth, svgHeight ); }, 1000);

  • gwolfe's avatar
    gwolfe
    Data Pipeline

    Thanks Ido_QBeeQ ! 

    The first 2 answers worked perfectly. I can't seem to get the third one to work. Here is the widget.js script. Anyway you could take a look and see if I am doing something wrong?

    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Highchart Highchart Color Heatmap
    // Version : 1.4
    // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    
    prism.registerWidget("colorheatmap", {
    	name : "colorheatmap",
    	family : "line",
    	title : "Color Heatmap",
    	iconSmall : "/plugins/ColorHeatmap/ColorHeatmap.png",
    	styleEditorTemplate: "/plugins/ColorHeatmap/styler.html",
    	style: {
    		LegendPosition	: 'Bottom',
    		XAxisPosition	: 'Bottom',
    		YAxisPosition	: 'Left',
    		ClickFilters	: 'Off'
    	},
    	data : {
    		selection : [],
    		defaultQueryResult : {},	
    		panels : [
    			{
    				name: 'X-Axis',
    				type: "visible",
    				metadata: {
    					types: ['dimensions'],
    					maxitems: 1
    				},
    				visibility: true
    			},
    			{
    				name: 'Y-Axis',
    				type: "visible",
    				metadata: {
    					types: ['dimensions'],
    					maxitems: 1
    				},
    				visibility: true
    			},
    			{
    				name: 'Value',
    				type: "visible",
    				itemAttributes: ["color"],
    				allowedColoringTypes: function() {
    					return  {
    						color: false,
    						condition: true,
    						range: true
    					};
    				},
    				metadata: {
    					types: ['measures'],
    					maxitems: 1
    				},
    				itemAdded: function(widget, item) {
    					item["format"] = 
    					{
    						mask : 
    					
    							{
    
    								type: 'number',
    								abbreviations: {
    									t: true,
    									b: true,
    									m: true,
    									k: true
    								},
    								separated: true,
    								decimals: 'auto'
    							},
    						color :
    							{
    								rangeMode : 'auto',
    								steps:0,
    								type: 'range',
    								
    							}
    					};
    					
    				},
    				visibility: true
    			},
    			{
    				name: 'filters',
    				type: 'filters',
    				metadata: {
    					types: ['dimensions'],
    					maxitems: -1
    				}
    			}
    		
    		],
    		
    		canColor: function (widget, panel, item) {
    			console.log('canColor');
    			
    			
    			if (panel.name == "Value") {
    				return true;
    			}
    			else {
    				return false;
    			}
    			
    		},
    
    		
    		
    		buildQuery: function (widget) {
    			console.log('buildQuery');
    			var query = { 
    					datasource: widget.datasource, 
    					format: "json",
    					isMaskedResult:true,
    					metadata: [] 
    				};
    				
    			
    			widget.metadata.panel("X-Axis").items.forEach(function (item) {
    
                            query.metadata.push(item);
                });				
    			
    			widget.metadata.panel("Y-Axis").items.forEach(function (item) {
    
                            query.metadata.push(item);
                });				
    				
    			widget.metadata.panel("Value").items.forEach(function (item) {
    
                            query.metadata.push(item);
                });			
    			
    			// force a sort by 
    			//if ($$get(query, 'metadata.1.jaql')) {
    			//	query.metadata[1].jaql.sort = "desc";
    			//};
    
    			// pushing filters
    			widget.metadata.panel('filters').items.forEach(function (item) {
    				item = $$.object.clone(item, true);
    				item.panel = "scope";
    				item.filterType = "widget";
    				query.metadata.push(item);
    			});
    			
    			
    			return query;		
    		},
    
    		
    		
    		//Create widget  Data Object and populate all values 
    		processResult : function (widget, queryResult) {	
    			console.log('processResult');
    			var 
    				Data = [],
    				nodeDimX,
    				nodeDimY,
    				XAxis = {},
    				YAxis = {},
    				Values = [],
    				minDataValue = 0,
    				maxDataValue = 0,
    				RangeMode = 'auto',
    				ColorFormatType = '',
    				minColor = '#FF0000',
    				maxColor = '#008000',
    				dashboardFiltersX = null,
    				dashboardFiltersY = null;
    			
    			
    			// find if there is any matching dashboard filters
    			nodeDimY = widget.metadata.panel("Y-Axis").items[0];
    			nodeDimX = widget.metadata.panel("X-Axis").items[0];
    			
    			widget.dashboard.filters.$$items.forEach(function(f){
    				if (f.isCascading){
    					f.levels.forEach(function(f2){
    						if(f2.dim == nodeDimY.jaql.dim) {
    							dashboardFilterY = f2.filter;
    						}
    						if(f2.dim == nodeDimX.jaql.dim) {
    							dashboardFilterX = f2.filter;
    						}
    					})
    				} else {
    					if (f.jaql.dim == nodeDimY.jaql.dim) {
    						dashboardFiltersY = f.jaql.filter;
    					};
    					if (f.jaql.dim == nodeDimX.jaql.dim) {
    						dashboardFiltersX = f.jaql.filter;
    					}
    				}
    			});
    			
    			
    			// Create Categories list for X Axis
    			
    			if (queryResult.columns().length > 0){
    				queryResult.columns()[0].forEach(function (item, i) {
    					XAxis[item.text] = 0;				
    				});			
    			};
    			
    			XAxis = Object.keys(XAxis)
    
    			// Create Categories list for Y Axis
    			if (queryResult.columns().length > 1){
    				queryResult.columns()[1].forEach(function (item, i) {
    					YAxis[item.text] = 0;
    				});			
    			}
    			YAxis = Object.keys(YAxis);
    			// sort the list if it is a datatime field
    			if (widget.metadata.panel('Y-Axis').items[0].jaql.datatype == 'datetime'){
    				YAxis.sort();
    			};
    			
    			
    			// Create value list in order to calc min, max values
    			if (typeof widget.metadata.panel("Value").items[0] != 'undefined'){
    				if (queryResult.columns().length > 2){
    					queryResult.columns()[2].forEach(function (item, i) {
    						Values[i] = item.data;
    					});	
    				};
    				maxDataValue = Math.max.apply(Math, Values);
    				minDataValue = Math.min.apply(Math, Values);
    			}
    			
    			
    			// Build the points for plotting the heatmap
    			queryResult.$$rows.forEach(function (item, i) {
    				
    				Data[i] = {
    						x		:(typeof item[0] != 'undefined') ? item[0].text : null,
    						y		:(typeof item[1] != 'undefined') ? item[1].text : null,
    						value	:(typeof item[2] != 'undefined') ? item[2].data : null, 
    						xdata	:(typeof item[0] != 'undefined') ? item[0].data : null,
    						ydata	:(typeof item[1] != 'undefined') ? item[1].data : null,
    						color 	: (typeof item[2] != 'undefined') ? item[2].color : null,
    						selected: false
    					}
    				
    				var isSelectedX = IsSelected(dashboardFiltersX, Data[i].x),
    					isSelectedY = IsSelected(dashboardFiltersY, Data[i].y);
    				
    				if (!(isSelectedX && isSelectedY)){
    					Data[i].color = Highcharts.Color(Data[i].color).setOpacity(0.3).get();
    				};
    				// Save selected state
    				Data[i].selected = (isSelectedX && isSelectedY); 
    				
    			});
    			
    			// determine the color mode and set min max colors accodingly 
    			if (typeof widget.metadata.panel("Value").items[0] != "undefined"){
    				ColorFormatType = widget.metadata.panel("Value").items[0].format.color.type;
    				
    			};
    			
    			
    			
    			switch (ColorFormatType){
    				case 'range':
    					RangeMode = widget.metadata.panel("Value").items[0].format.color.rangeMode;
    					if (RangeMode == 'auto') {
    						minColor = '#FF0000',
    						maxColor = '#008000'
    					}
    					else {
    						minColor = widget.metadata.panel("Value").items[0].format.color.min;
    						maxColor = widget.metadata.panel("Value").items[0].format.color.max;
    					}
    						
    					break;
    					
    				case 'condition':
    					minColor = widget.metadata.panel("Value").items[0].format.color.conditions[0].color;
    					maxColor = widget.metadata.panel("Value").items[0].format.color.conditions[widget.metadata.panel("Value").items[0].format.color.conditions.length - 1].color;
    					//minColor = null;
    					//maxColor = null;
    					break;
    				default:
    					minColor = null;
    					maxColor = null;
    			}
    			
    			return {minColor,maxColor,maxDataValue,minDataValue,XAxis,YAxis, Data};
    			
    			
    			function IsSelected(dashboardFilters, Item){
    				if (dashboardFilters == null) {
    					return true
    				}
    				else if (dashboardFilters && (typeof dashboardFilters.all != 'undefined')) {
    					return true
    				}
    				
    				else if (dashboardFilters && (typeof dashboardFilters.exclude != 'undefined')) {
    					var ItemsToExclude = dashboardFilters.exclude.members;
    					return (ItemsToExclude.indexOf(Item) == -1) ? true : false
    				}
    				
    				else if (dashboardFilters && (typeof dashboardFilters.members != 'undefined')) {
    					var ItemsToInclude = dashboardFilters.members;
    					if (ItemsToInclude.length == 0) {
    						return true
    					}
    					else {
    						return (ItemsToInclude.indexOf(Item) == -1) ? false : true
    					}
    				
    				}
    				
    				else {
    					return false;
    				}
    	
    			}
    		}
    	},
    	
    	beforequery: function(widget, args){
    		
    		var	
    			widgetPanels = [];
    			
    		// if filter mode is slice/filter then do nothing
    		if (widget.options.dashboardFiltersMode == "filter"){
    			return;
    		};
    			
    		widgetPanels.push(widget.metadata.panel("X-Axis").items[0]);
    		widgetPanels.push(widget.metadata.panel("Y-Axis").items[0]);
    		
    		for (var j=0; j <= (widgetPanels.length - 1); j++){
    			var nodeDim = widgetPanels[j];
    			
    			//	Look for any dashboard filters
    			var dashboardFilters = prism.activeDashboard.filters.$$items;
    
    			//	Loop through the metadata
    			for (var i=args.query.metadata.length-1; i>0; i--){
    
    				//	Does this item match the node's dimension AND is a dashboard filter?
    				var isMatch = (args.query.metadata[i].panel == "scope") && (args.query.metadata[i].jaql.dim == nodeDim.jaql.dim),
    					isNotWidgetFilter = (args.query.metadata[i].filterType !== "widget"),
    					isWidgetFilter = (args.query.metadata[i].filterType == "widget"),
    					isDashboardFilter = $.grep(dashboardFilters, function(w){
    						return (w.jaql.dim == args.query.metadata[i].jaql.dim) && (typeof w.jaql.filter.all == "undefined");
    					}).length > 0;
    				
    				if (isMatch && isNotWidgetFilter && isDashboardFilter) {
    				//if (isMatch && isDashboardFilter) {
    					
    					//	Create a new copy of the filter object
    					var matchFilter = $$.object.clone(args.query.metadata[i], true);
    
    					//	Remove the panel attribute
    					delete matchFilter.panel
    
    					//	Include with the node's dimension metadata
    					//nodeDim.jaql.in = {selected: matchFilter}
    					if (isWidgetFilter && defined(matchFilter.jaql.filter)) {
    						nodeDim.jaql.filter = matchFilter.jaql.filter;
    					}
    
    					//	Remove from the metadata
    					args.query.metadata.splice(i,1);
    				}
    			}		
    		}
    		
    	},		
    
    	render : function (widget, event) {
    		console.log('render');
    		var element = $(event.element),
    			svgHeight = $(element).height(),
    			svgWidth = $(element).width();
    			
    		
    		element.empty();
    		
    		var num = Math.floor(Math.random() * 1000000);
    		var MyDiv = element[0],
    			ObjectID = widget.oid,
    			ChartDivName = "colorheatmap-" + ObjectID + "-" + num;
    			
    		MyDiv.setAttribute("id",ChartDivName);
    		MyDiv.setAttribute("style","width: 99%; height: 99%; margin: 0 auto");
    			
    //		element.append('<div style="width=97% height=97% margin: 0 auto" id="' + svgID + '"></div>');
    		
    		setTimeout(() => { DisplayColorHeatmap ( widget, ChartDivName, svgWidth, svgHeight ); }, 1000);
    
        options: {
            dashboardFiltersMode: "select",
            selector: false,
            title: false
        },
        sizing: {
    
            minHeight: 120, //header
            maxHeight: 2048,
            minWidth: 320,
            maxWidth: 2048,
            height: 200,
            defaultWidth: 512
        }
    
    });