Sisense Community logo
     
    • Community Feedback
    • Chapters
    • Events
    • Forums
      • Help and How To
      • Product Feedback Forum
      • Strategy & Use Cases
    • Blogs
    • KB Docs
      • KB Docs
      • Add-Ons & Plug-Ins
      • APIs
      • Best Practices
      • Blox
      • CDT
      • Cloud Managed Service
      • Data Models
      • Data Sources
      • Embedding Analytics
      • How-Tos & FAQs
      • Onboarding
      • PySisense
      • Security
      • Sisense Administration
      • Sisense Intelligence & AI
      • Troubleshooting
      • Widget & Dashboard Scripts
    • Support
    • Learning
      • Sisense Academy: Free Courses and Certifications
      • Official Developer Documentation
      • Official Product Documentation
      • Official Sisense Youtube Channel
      • Sisense Compose SDK Playground
      • Official Sisense Discord
    • Use Case Gallery
    •      
    Discussions
    •                    
    •                    
    •                    
    •                    
    •                    
    •                    
    •                    
    •                    
    •                    
    •                    
    •                    
    •                    
    •                    
    •                    
    •                    
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   
    Discussions
    • TagsChevronRightIcon
    Code-first Analytics
    • Blog banner
      • Widget & Dashboard ScriptsChevronRightIcon

      Hiding Widgets if a Widget Has No Results [Linux]

                                                                                                               

      Hiding Widgets if a Widget Has No Results [Linux] Introduction A common dashboard design requirement is hiding widgets that have no data. This article includes a widget script that conditionally hides an indicator widget when its primary value is empty or represents an N/A like value. This behavior is commonly requested when dashboard filters or formulas result in no meaningful value and the widget should be visually hidden rather than showing an empty or zero indicator. The article also includes an alternative dashboard-level approach that hides widgets based on filter selections, without inspecting widget query results. This alternative is derived from the linked external blog post . This is applicable to both on-cloud and on-prem Sisense in all recent Sisense versions. Use Case Customers often want indicator widgets to disappear when their calculated value is not meaningful. Common examples include: Filters resulting in no matching data Calculations returning N/A, null, or empty values Conditional metrics that only apply to certain filter selections Rather than showing an empty indicator, this approach hides the widget entirely and restores it automatically when the value becomes valid again. Layout Considerations For best visual results, it is ideal to use one of these two layouts for the indicator widgets that may be hidden: Place the indicator widget in its own dashboard row Place it at the end of a row Hiding a widget via a script does not automatically resize or reflow other widgets on the same row. Step by Step Guide Widget Script to Hide Widget Based on Indicator Value This widget script is applied directly to the indicator widget. It evaluates the widget’s primary value after each render and hides or shows the widget accordingly. Behavior If the primary value is null, empty, or an N/A like string, the widget container is set to display: none. When the value becomes valid and not null again, the widget is restored to visibility and redrawn to ensure correct indicator rendering. A guard variable prevents infinite redraw loops, since a redraw triggers the widget ready event. A debug flag allows optional console logging when needed. Widget Script /** * Hide widget when its primary indicator value is empty or N/A-like. * * Behavior: * - If the value is empty, set the widget container to display "none". * - If the returned value becomes a number or valid value, restore display style to original and redraw * - A redraw triggers "ready" again, so a guard variable prevents a redraw loop. * * Debug: * - Set debug variable = true to enable console logging to track script status. * * For best results use on indicator in own row or at end of row, if other widgets exist on row, empty space will appear in dashboard */ widget.on("ready", function () { function run() { var debug; var suppressNextReady; var hideValues; debug = false; suppressNextReady = false; hideValues = [ "n/a", "#n/a", "na", "none", "null", "undefined" ]; // Function to turn console logging on or off function log(message, data) { if (!debug) { return; } if (data === undefined) { console.log("[hide-empty-indicator] " + message); return; } console.log("[hide-empty-indicator] " + message, data); } // Widget CSS selector function getWidgetElement() { return document.querySelector('widget[widgetid="' + widget.oid + '"]'); } // Get value of primary indicator value function getPrimaryValue() { if ( widget.queryResult && widget.queryResult.value && widget.queryResult.value.data !== undefined ) { return widget.queryResult.value.data; } try { if ( widget.queryResult && widget.queryResult.data && widget.queryResult.data.length ) { return widget.queryResult.data[0][0]; } } catch (e) { log("Value read failed for data[0][0].", e); } if (widget.queryResult && Array.isArray(widget.queryResult)) { if (widget.queryResult.length && widget.queryResult[0].length) { if (widget.queryResult[0][0]) { return widget.queryResult[0][0].Value; } } } return null; } function shouldHide(value) { var text; var normalized; if (value === null || value === undefined) { return true; } text = String(value).trim(); if (!text) { return true; } normalized = text.replace(/\\/g, "/").toLowerCase(); return hideValues.indexOf(normalized) !== -1; } function isElementHidden(element) { if (!element) { return false; } return element.style.display === "none"; } function hideWidget(element) { if (!element) { return; } if (element.style.display === "none") { return; } element.style.display = "none"; log("Hid widget due to empty/N/A-like value."); } function showWidgetAndRedrawIfNeeded(element) { var wasHidden; if (!element) { return; } wasHidden = isElementHidden(element); element.style.display = ""; if (!wasHidden) { log("Widget already visible."); return; } if (typeof widget.redraw !== "function") { log("Widget restored, redraw not available."); return; } suppressNextReady = true; log("Widget restored, triggering redraw."); widget.redraw(); } function applyRule() { var element; var primaryValue; element = getWidgetElement(); if (!element) { log("Widget container element not found."); return; } if (widget.queryResult === undefined) { log("queryResult is not available yet, keeping widget visible."); element.style.display = ""; return; } primaryValue = getPrimaryValue(); log("Primary value evaluated.", primaryValue); if (shouldHide(primaryValue)) { hideWidget(element); return; } showWidgetAndRedrawIfNeeded(element); } function onReady() { if (suppressNextReady) { suppressNextReady = false; log("Ready fired after redraw, applying rule without redraw."); applyRule(); return; } applyRule(); } onReady(); } run(); }); Notes The script uses display: none instead of jQuery hide or show to avoid layout and rendering issues with indicator widgets. Redraw is triggered only when restoring visibility, not when hiding. The script relies only on the widget ready event, which fires again after redraw and filter changes. Dashboard Script to Hide Widgets Based on Filter Selections As an alternative, widgets can be hidden purely based on filter selections, without checking whether the widget returns data. This approach is useful when visibility rules are deterministic based on filters. This method uses a dashboard script and CSS classes to hide widget containers. Example Dashboard Script dashboard.on('filterschanged', function (se, ev) { let filterName = 'Region' //mapping of filter items and widgets to be hidden. //if selected filter item is not available in the list, widgets in 'default' key will be hidden let itemWidgetMapping = { 'Midwest':['6390b5a285a029002e9e2ad6'], 'South': ['6238887ba77683002ea4425b'], 'West':['6390b5a285a029002e9e2ad6', '6238887ba77683002ea4425b'], 'default':[] } selectedFilter = ev.items.find(el=>el.jaql.title == filterName) let selectedItem = 'default' if(selectedFilter && selectedFilter.jaql.filter.members) selectedItem = selectedFilter.jaql.filter.members[0] //unhide all widgets first and then hide widgets based on selected filter $(`widget`).closest('.dashboard-layout-subcell-host').removeClass('dontshowme-parent') if(selectedItem in itemWidgetMapping){ for (const [key, value] of Object.entries(itemWidgetMapping)) { if(key == selectedItem){ itemWidgetMapping[key].forEach(function (item, index) { $(`widget[widgetid="${item}"]`).closest('.dashboard-layout-subcell-host').addClass('dontshowme-parent') }); } } } else{ itemWidgetMapping['default'].forEach(function (item, index) { $(`widget[widgetid="${item}"]`).closest('.dashboard-layout-subcell-host').addClass('dontshowme-parent') }); } }); Choosing the Right Approach Generally the widget script is best suited when: Visibility depends on whether data is returned The indicator value can be empty due to calculations or filters Generally the dashboard script is best suited when: Visibility depends only on filter selections Centralized control over multiple widgets is required These approaches are alternatives and should not be used simultaneously for the same widgets. Conclusion Hiding indicator widgets based on their returned value can potentially improve dashboard clarity and user experience. The widget script approach provides result aware behavior, while the dashboard script approach offers deterministic, filter based control. Both methods are powerful tools for customizing dashboard widget visibility. Two Full Row Indicator Widgets, both visible First Row Indicator Widget is now hidden, by script, due to no data Two Indicators in one row, both visible Second Indicator is now hidden by script, due to no data Disclaimer: This post outlines a potential custom workaround for a specific use case or provides instructions regarding a specific task. The solution may not work in all scenarios or Sisense versions, so we strongly recommend testing it in your environment before deployment. If you need further assistance with this, please let us know.

      Jeremy Friedel
      Jeremy FriedelPosted 1 week ago
      0
               
    • Blog banner
      • Add-ons & Plug-InsChevronRightIcon

      Plugin - Custom Coloring of Bar and Column Chart Type Widgets (barChartCustomColor)

                                                       

      Plugin - Custom Coloring of Bar and Column chart-type widgets This plugin  modifies the color scheme of bar and column chart-type widgets to match the current color palette of the dashboard. Installation To install this plugin, download and unzip the attachment. Then drop the barChartCustomColor folder into your plugins folder (/opt/sisense/storage/plugins). Enable the plugin on the Add-ons tab in the Admin section, wait for the plugin to build, and the plugin will be enabled. The plugin API can also be used, as well as the file management UI . Notes When a bar or column chart type Sisense widget is very straightforward and focused and does not have multiple values, breaks by's, categories, or conditional coloring, it can sometimes appear relatively mono-color but still be the most effective way to quickly visually communicate important data.   While Sisense includes numerous powerful and varied methods and options to change widget styling  and includes functionality to set bar color to vary based on the bar value , it sometimes may be desired to use the dashboard palette to vary the bar colors independently of bar value and guarantee a colorful widget regardless of the data and current filter state of the current dashboard and widget. This plugin allows the current dashboard palette to be used in this manner in a simple and quick matter and allows this to be applied quickly to an entire dashboard at once. Linking the widget coloring to the dashboard palette allows this color scheme to be quickly changed in the native UI without modifying individual widgets. This plugin also allows using a color dictionary config option to modify the coloring of a value in all widgets this plugin is enabled in.       This plugin  uses the processresult widget event to modify the color parameter of each bar or column in a series.   The dashboard palette is retrieved using the getPalette() function within the dashboard style parameter, which returns the current dashboard palette. This can be used in other plugins and scripts.     dashboard.style.getPalette()       This plugin is enabled via dashboard or widget scripts that set the widget parameter changeColor to true for a widget.   For a widget script, this is as simple as adding this one line to the script:     widget.changeColor = true;       Adding this three-line dashboard script will set this parameter to true for all widgets in the dashboard:     dashboard.on('widgetinitialized', function (_, dashObj) { dashObj.widget.changeColor = true; });     This can be modified with custom logic as needed, for example, based on widget title or ordering in the dashboard. If this option is enabled for a type of widget this plugin does not apply to, it will simply be ignored by the plugin. This plugin ignores widgets with  Break By's or Date Categories, or widgets that are not bar or column chart-type widgets. The color scheme is based on the current dashboard palette.    Changing the dashboard palette using the standard Sisense palette UI will result in a matching change of all widgets in the dashboard where this plugin is enabled. The config file of this plugin includes an option called colorDictionary, this can be used to override the standard palette color for all instances this value appears as the bar category, for all widgets this plugin is enabled for, regardless of the dashboard palette. Any standard HTML color naming format may be used in the dictionary config value. For example, if the colorDictionary is set to:     colorDictionary : { 'Bikes': '#AA6C39', 'ABC' : 'yellow' }      Then the ABC bar or column will be yellow in the widget, regardless of the current widget palette or positioning. This will apply to all widgets where this plugin is active. This plugin can be used as a basic template for your own Sisense plugins that run on a specific widget or dashboard event, that can be enabled or disabled via widget script, and that includes a configuration file to modify settings without modifying code files.        How did the plugin work for you? What other type of plugin are you looking to learn more about? Let me know in the comments!

      Jeremy Friedel
      Jeremy FriedelPosted 2 years ago • Last reply 1 month ago
      1
               
    • Blog banner
      • APIsChevronRightIcon

      UserReplaceTool - Automating Dashboard Ownership Transfers - Useful for Deleting User Accounts

                                                                                                       

      Automating Dashboard Ownership Transfer in Sisense with UserReplaceTool Managing and deleting user accounts in Sisense can create manual processes when users leave an organization or change roles. A frequent issue is the reassignment of dashboard ownership to prevent losing Sisense dashboards when a given user account is deleted, as deleting a Sisense user will delete all dashboards owned by that user. The UserReplaceTool addresses this task by automating the transfer of dashboard ownership of all dashboards owned by a given user, ensuring continuity and data integrity. Overview UserReplaceTool is a Python-based, API-based Tool solution designed to seamlessly transfer the ownership of dashboards and data models from one user to another in Sisense. This tool simplifies and automates this process, allowing organizations to reassign dashboard ownership without manual processes or the risk of losing dashboards and widgets. All components are accomplished by using Sisense API endpoint requests. Key Features Automated Dashboard Transfer : Reassigns ownership of all dashboards from the current user to a designated replacement user. Data Model Sharing : Ensures that all data models accessible and editable by the previous user are shared with the replacement user. Batch User Processing : Capable of handling multiple user transfers to a replacement user in a single operation, enhancing efficiency. Complete Logging:  All dashboards and datasource transferred are logged both in the console and in a separate log file. Setup Instructions 1. Setting Up the Environment To run the tool within a Python virtual environment , follow these steps: Activate the Python Virtual Environment : source /venv/bin/activate Create a Virtual Environment (if not already present): python3 -m venv .venv Install Dependencies : pip3 install -r requirements.txt For manual installation, including without using a Python virtual environment: pip3 install urllib3 jsonpath_ng pyyaml requests colorama 2. Configuration Edit the settings.yaml file to configure the tool. Key parameters include: Sisense Domain and Port : Specify the URL and port of your Sisense server, which is used for making API requests. API Bearer Token : Provide an admin-level bearer token for API authentication. See the  Sisense API Bearer Token Documentation for instructions on generating and using Bearer Tokens. Users to Replace : List the user IDs to be replaced. User IDs can be retrieved via the Users API or using the console command prism .user._id. Replacement User : Specify the user ID of the new replacement owner of all dashboards. This should typically be an admin level user. Data Model Sharing : Enable or disable the sharing of data models with the Replacement user (True or False), usually True. Dashboard Ownership Transfer : Enable or disable the transfer of dashboard ownership (True or False), usually True. Unlike Dashboards, if a user is deleted, the datasources themselves are not deleted from the server, ownership is automatically transferred to the main System Admin of the Sisense server.  3. Running the Tool Run the tool with the following command:   python3 replaceUser.py Practical Considerations Admin and Network Access : Ensure you have admin-level API access to the Sisense instance. Python Environment : Python3 and pip should be installed on the machine running the tool. All dependencies can be installed using Pip, and a Python virtual environment can be used. Once a Python Virtual Environment folder is set up it can be shared with the Tool and run directly on all systems using the same OS, but it is not cross OS compatible. By automating the transfer of dashboard ownership, UserReplaceTool provides a reliable and efficient solution for managing user transitions in Sisense. This ensures that datasources and dashboards remain accessible and under the control of the appropriate users, maintaining the continuity of Sisense resources. For further customization and configuration details, refer to the attached full Python Tool, which includes a README file and modify the "settings.yaml" file as necessary.    

      Jeremy Friedel
      Jeremy FriedelPosted 1 year ago • Last reply 3 months ago
      3
               
    • BenWalkerRH

      Help and How-To

               
      BenWalkerRH
      Posted 8 months ago • Last reply 7 months ago
      Dynamically changing colours on value labels
                               

      Does anyone know if this if possible either at a widget level AND/OR at a dashboard level? I've tried a bunch of scripts from ChatGPT but none that work as intended.  They either amend the colours but dont respect and changes being mad to rendering such as cell size changes and filters applied etc, or the reverse where it respects the rendering but not the colours changing.. 

                                             
      5
               
    • Astroraf

      Help and How-To

               
      Astroraf
      Posted 7 months ago • Last reply 7 months ago
      Conditional Format in BloX using an image
                               

      Hi harikm007​ , DRay​ , Liliia_DevX​   I am using BloX to display a conditon format based on a if a value is above 10% or below 10% and then display a green or red arrow I have in my plugins folder to show.  My script goes as follows: { "style": "@import url('https://fonts.googleapis.com/css2?family=Manrope:wght@700;800&display=swap');", "script": "", "title": "", "conditions": [ { "minRange": "-Infinity", "maxRange": 0.10, "image": "/plugins/assets/icons/red_arrow.png", "color": "#D34A4A", "fontSize": "14px", "fontWeight": "600" }, { "minRange": 0.10, "maxRange": "Infinity", "image": "/plugins/assets/icons/green-up-arrow.svg", "color": "#079B65", "fontSize": "14px", "fontWeight": "600" } ], "titleStyle": [ { "display": "none" } ], "showCarousel": false, "body": [ { "type": "ColumnSet", "columns": [ { "type": "Column", "width": "stretch", "style": { "width": "430px", "height": "145px", "box-sizing": "border-box", "padding": "16px" }, "items": [ { "type": "ColumnSet", "columns": [ { "type": "Column", "width": "stretch", "items": [ { "type": "TextBlock", "text": "No shows - last full month", "style": { "font-family": "Inter, sans-serif", "font-size": "16px", "font-weight": "700", "text-align": "left", "color": "#212A31", "margin": "0" } } ] }, { "type": "Column", "width": "auto", "horizontalAlignment": "right", "style": { "text-align": "right", "min-width": "14px" }, "items": [ { "type": "ColumnSet", "style": { "align-items": "center" }, "columns": [ { "type": "Column", "width": "auto", "items": [ { "type": "Image", "url": "{conditions:image}", "altText": "delta", "horizontalAlignment": "right", "style": { "width": "12px", "height": "10px", "margin-right": "6px", "margin-top": "2px" } } ] }, { "type": "Column", "width": "150", "items": [ { "type": "TextBlock", "text": "{panel:# of unique Patient ID}", "style": { "font-family": "Inter, sans-serif", "font-size": "14px", "font-weight": "600", "color": "{conditions:color}", "text-align": "right", "margin": "0" } } ] } ] } ] } ] }, { "type": "TextBlock", "text": "{panel: No Show}", "style": { "margin-top": "16px", "font-family": "Manrope, Inter, sans-serif", "font-size": "28px", "line-height": "32px", "font-weight": "700", "text-align": "left", "color": "#212A31" } }, { "type": "TextBlock", "text": "Avg 10%", "style": { "margin-top": "8px", "font-family": "Inter, sans-serif", "font-size": "12px", "font-weight": "500", "text-align": "left", "color": "#969696" } } ] } ] } ], "actions": [] }  

                                             
      3
               
    • Astroraf

      Help and How-To

               
      Astroraf
      Posted 8 months ago • Last reply 7 months ago
      Breaky By Column with two Values: Is it Possible?
                       

      Hello DRay​ Liliia_DevX​ , I am curious if there is a way to display two values with a break by by a category in Sisense? This is a provided example of what I am trying to achieve. 

                                             
      2
               
      • Help and How-ToChevronRightIcon
                       
      How to create a filter within a widget?
      Astroraf
      Astroraf
      Posted 9 months ago • Last reply 8 months ago
      8
               
    • mikemieszczak

      Help and How-To

               
      mikemieszczak
      Posted 10 months ago • Last reply 8 months ago
      Hide Widget based on grouped by Column Values
                               

      Hello I'm looking to hide a specific widget id if a specific value exists within a column value.  I started with  dashboard.on('widgetrefreshed', function (se, ev) {   widgetList = ['682f7ab1602b5d7f74c97e6f', ]   if(widgetList.includes(ev.widget.oid)) { $(`widget[widgetid="${ev.widget.oid}"]`).closest('.dashboard-layout-subcell-host').addClass('dontshowme-parent') } });   but I am not sure how to check if the value for a column called test_benchmarks  contains 'ctv'

                                             
      9
               
    • radorado

      Help and How-To

               
      radorado
      Posted 10 months ago • Last reply 8 months ago
      Need swagger/openapi spec to generate client
                       

      Hello! My team is integrating with your system and I wanted to generate (via codegen-swagger or @openapitools/openapi-generator-cli) the client that is supposed to talk to your API. For that purpose I would need access to you swagger specification or openapi specification document via link or something. Do you have such specification somewhere and if yes could you provide me a link for it or help me navigate to it? Best regards, Rado

                                             
      5
               
      • Help and How-ToChevronRightIcon
                       
      Colored labels in table
      HQ_Dev_Prod
      HQ_Dev_Prod
      Posted 1 year ago • Last reply 9 months ago
      10