Search Results
95 items found for ""
- Streamlining Script Management in Sisense: Overcoming the Challenge of Widget Customizations
On our website, we offer a variety of customization scripts that enhance the functionality and interactivity of Sisense widgets and dashboards. Many users have implemented these scripts to optimize their workflows and create tailored visualizations. However, a common issue arises when trying to apply these scripts to multiple widgets or dashboards: the need to add the same script separately to each widget. For example, if you're implementing a measure changer dropdown across five different widgets, you must manually add the script to each one. While this approach works, it poses several challenges: Disadvantages of Adding Scripts Separately to Each Widget or Dashboard: Increased Maintenance Effort:  Every time a script needs to be updated or modified, it must be done individually for each widget or dashboard, making the process tedious and prone to errors. Inconsistent Implementations:  Manually adding scripts to each widget can lead to inconsistencies in how they function across different dashboards, especially if a script is overlooked during an update. Time-Consuming:  Applying scripts one-by-one across multiple widgets and dashboards can be a time sink, especially when scaling or making frequent updates. Higher Risk of Errors:  The more manual intervention required, the higher the risk of coding mistakes or missing widgets in the update process. To address these challenges, there are two key solutions: 1. Creating a Plugin for the Feature Developing a plugin for specific features centralizes script management. A plugin allows you to apply scripts from a single source, ensuring that updates only need to be made in one place. Advantages of Creating a Plugin: Centralized Codebase:  The script lives in one location, so changes only need to be made once, ensuring consistency across the platform. Easy Maintenance:  Future updates or changes can be done within the plugin, reducing the chances of errors and streamlining the update process. Ideal for Complex Features:  This option is especially valuable when implementing complex features or custom visualizations that need to be reused across dashboards. However, creating a plugin is typically not necessary for smaller customizations, as it requires development time and effort that may outweigh the benefits for minor script adjustments. If you're considering creating a custom plugin for your Sisense environment, I offer specialized consulting services  to help you design and develop the right solution for your needs. Feel free to contact me  to discuss how we can build the perfect plugin or do customization for your business. 2. Using Paldi’s Widget Script Manager Plugin For users looking for an easier way to manage smaller customizations across multiple widgets, Paldi Solutions' Widget Script Manager  is the ideal solution. This plugin simplifies the process of applying scripts across widgets and dashboards without the need for repetitive coding. Key Benefits of the Widget Script Manager: Centralized Script Management:  All scripts are managed in one location, ensuring consistency and easier updates across all widgets and dashboards. Effortless Deployment:  You can apply scripts to specific widgets, widget types, or entire dashboards with minimal effort. This is particularly useful for deploying the same script to multiple widgets without needing to manually add it each time. Pre-built Script Samples:  The plugin comes with useful script samples, so you can quickly implement common use cases without needing to write scripts from scratch. Customizable Combinations:  Users can configure which widgets or dashboards a script applies to, providing flexibility without manual intervention on each element. Error Reduction:  By managing scripts centrally, you reduce the chances of discrepancies or errors between dashboards, ensuring a consistent experience. Simplified Maintenance:  Any updates or changes are made once within the plugin, making the process much more manageable and efficient. Intuitive UI Management:  Designers can easily enable or disable scripts from the widget or dashboard menu, without needing to dive into code. This makes script management accessible even to non-developers. Why Choose the Widget Script Manager for Small Customizations? For simple UI/UX enhancements and visual adjustments, Paldi’s Widget Script Manager provides a quick and efficient solution. You get the benefits of centralized script management without the need to develop a custom plugin, saving time, reducing errors, and keeping your Sisense environment organized. If you’re interested in using the Widget Script Manager, contact me  for exclusive discounts  when you purchase the plugin through this website. Don't miss the opportunity to streamline your Sisense customization efforts with this powerful tool!
- Pivot2 - Spread color from one column to entire row
Currently, in pivot, we can set colors to a column based on its value. In that case color will get applied to only that column. Below script will spread color from a column to entire row widget.on('ready', function(se, ev) { panelName = 'Value 1' //Update your panel name from which color needs to spread to entire row if (prism.activeWidget == null) widgetelement = $('[widgetid="'+ se.oid + '"] pivot2 .pivot-scroller table tbody tr') else widgetelement = $('.pivot-scroller table tbody tr', element) var colIndex = -1 $(widgetelement).each(function(index, trElement){ if(index == 0) { $(trElement).find('td .table-grid__content .table-grid__content__inner').each(function(tdIndex, tdElement){ if ($(tdElement).text() == panelName){ colIndex = tdIndex } }) } else{ if(colIndex >= 0){ bgColor = $(trElement).find('.table-grid__cell--col-' + colIndex).css('backgroundColor') $(trElement).find('td').each(function(tdIndex, tdElement){ $(tdElement).css('backgroundColor', bgColor) }) $(widgetelement).each(function(rowIndex, rowElement){ if(rowIndex > 0 && index == rowIndex){ $(rowElement).find('td').css('backgroundColor', bgColor) } }) } } }) })
- Switchable Measure Dropdown
Here is a script to add a dropdown to switch between different measures/calculation. For example, in below screenshot, each item in dropdown represent different calculations and when we select an item from it, chart will show corresponding calculated values in Y-Axis. (The X-axis won't change) Steps: Create a bar/column/line/are chart Widget should contain only one category(dimension). You can create as many Values panels as required and enable only one panel. The script will generate one button per Value panel and will be able to switch between panels by clicking on buttons. 3. Add below script to widget 4. Save the script and refresh widget widget.on('processresult', function(se, ev){ ev.result.chart.spacing = [20, 20, 77, 20 ] }); widget.on("domready", function(w){ chart = w.chart[0][Object.keys(w.chart[0])[0]].hc var buttonList = new Array(w.metadata.panels[1].items.length) chartContainer = $('.highcharts-container', element) dropdownHTML = `` if($(`#select-${w.oid}`).length) { $(`#select-${w.oid}`).remove() chartContainer.height(chartContainer.height() + 77); } chartContainer.before(dropdownHTML) $.each(w.metadata.panels[1].items, function(index, value){ $(`#select-${w.oid}`).append(`${value.jaql.title}`) }) chartContainer.height(chartContainer.height() - 77); selecteIndex = w.metadata.panels[1].items.findIndex(el=>el.disabled == false) document.getElementById(`select-${widget.oid}`).value = 'Item' + selecteIndex var select = document.getElementById(`select-${widget.oid}`); select.addEventListener('change', (e) => { var selectedPanelIndex = parseInt(e.target.value.replace('Item', '')) $.each(w.metadata.panels[1].items, function(itemIndex, itemValue){ if(itemIndex == selectedPanelIndex) itemValue.disabled = false else itemValue.disabled = true }) widget.refresh(); }); });
- Hide a Column from Table Widget
Sometimes we may need to hide a column from table widget, so that it will appear only in the downloaded CSV file. Here is a solution to achieve this. Steps: Create a table widget Add below widget script. Update the variable columnIndex with index of column to be hidden. (index is a number assigned to columns starting with 1. In above screenshot, State column has index 1, Country has index 2 and Region has index 3) Save the script and refresh the dashboard widget.on('domready', function(se, ev){ let columnIndex = 3 $(`table tr > *:nth-child(${columnIndex})`, element).css('display', 'none') const elementToObserve = $('table tbody', element)[0]; const observer = new MutationObserver(function(e) { for(const m of e) { if (m.type === 'childList') { $.each(m.addedNodes, function(index, value){ $(value).find(`td:nth-child(${columnIndex})`).css('display', 'none') }) } } }) observer.observe(elementToObserve, {subtree: true, childList: true}); })
- Blox drop-down v2 - Without 'Apply' button
We know its possible to create a dropdown using blox. But it requires a button to apply the filter to dashboard. Here is a solution to create blox dropdown without a button. Filter will get applied as soon as the user selects an item from dropdown. Steps: Create new Blox widget and add a dimension under 'items' panel. Add same dimension as a dashboard filter. 2. Add below Blox script. Replace the name ' Region ' in below script with the name of dimension you added in the above step. { "style": "select {border-radius:5px}", "script": "", "title": "", "titleStyle": [ { "display": true } ], "showCarousel": true, "carouselAnimation": { "showButtons": false }, "body": [ { "type": "Container" }, { "type": "ColumnSet", "separator": false, "spacing": "default", "columns": [ { "type": "Column", "spacing": "none", "width": "250px", "items": [ { "type": "Container", "spacing": "none", "width": "220px", "height": "50px", "style": { "color": "black", "padding-top": "10px", "margin-left": "10px", "backgroundColor": "white" }, "items": [ { "type": "Input.ChoiceSet", "id": "data.filters[0].filterJaql.members[0]", "class": "dropdownChoices", "value": "Reseller", "displayType": "compact", "choices": "{choices:Region}", "style": { "color": "#656566", "padding-left": "10px", "margin-left": "10px", "backgroundColor": "grey", "border": "2px solid #aac7e6", "height": "35px", "font-size": "15px" } } ] } ] } ] } ], "actions": [] } 3. Add below widget script. This is to add 'All' in dropdown and apply filter as son as user picks an item widget.on('processresult', function(se, ev){ allObject = [{ "Panel": "Region", "Value": "All", "Text": "All", "HasValue": true }] ev.result.unshift(allObject) }) widget.on('ready', function(se, ev){ var filterName = 'Region' var select = document.getElementById(`data.filters[0].filterJaql.members[0]`); dashboardFilter = prism.activeDashboard.filters.$$items.find(el => el.jaql.title == filterName) if(dashboardFilter && dashboardFilter.jaql.filter && dashboardFilter.jaql.filter.members) { select.value = dashboardFilter.jaql.filter.members[0] } select.addEventListener("change", function(e){ if(e.target.value == "All") { filter = { "explicit": false, "multiSelection": true, "all": true } }else { filter = { "explicit": true, "multiSelection": true, "members": [ e.target.value ] } } dashboardFilter = prism.activeDashboard.filters.$$items.find(el => el.jaql.title == filterName) var filterOptions = { save: true, refresh: true, } dashboardFilter.jaql.filter = filter prism.activeDashboard.filters.update(dashboardFilter, filterOptions) }); })
- Filter Buttons v2 - With 'All' button
We already have a script to add filter buttons in a widget . Here is an upgraded version of the script which will add another button 'All' to select all items in the filter. Also added functionality to unselect a filter. For example, if you click on an already selected button, it will get unselected and display all items. Steps: Create a Line/Column/Bar/Area/Pie chart Add below script to the widget and update the variable ' dimension ' with name of dimension in the format "[Table Name.Column Name]". Items in this field will be displayed as button. Add the same column in widget filter pane. Save the script and refresh widget. widget.on('processresult', function(se, ev){ ev.result.chart.marginTop= 60 }); var dimension = "[Records.Region]" var normalState = { fill: '#fcd4d2', stroke: '#cc4e45', r: 3, style: { color: '#6D6D6D', borderWidth : 0 } }, hoverState = { fill: '#d6665e', stroke: '#cc4e45', r: 3, style: { color: '#6D6D6D', borderWidth : 0 } }, pressedState = { fill: '#c9483e', stroke: '#cc4e45', r: 3, style: { color: '#FFFFFF', borderWidth : 0 } }, disabledState = { fill: '#EEEDFA', stroke: '#ADABF6', r: 5, style: { color: '#6D6D6D', borderWidth : 0 } }, callback = function () { } widget.on("domready", function(w){ let chart = w.chart[0][Object.keys(w.chart[0])[0]].hc let items = getItemList(w).values; //items.length = 10 let itemlist = Array.from(items, x=>x[0].data) let buttonList = new Array(itemlist.length + 1) let widgetFilter = widget.metadata.panels[3].items.find(el => el.jaql.dim == dimension) $.each(itemlist, function(index, value){ buttonList[0] = chart.renderer.button('All', 10, 10, callback, normalState, hoverState, pressedState, disabledState) .attr({ zIndex : 10, height: 15, width: 80, 'text-align': 'center' }) .css({width: '116px'}) .on('click', function() { widgetFilter.jaql.filter = { "explicit": false, "multiSelection": true, "all": true } widget.refresh(); }) .add(); }) $.each(itemlist, function(index, value){ buttonList[index+1] = chart.renderer.button(value, 10 + ((index+1) * 100), 10, callback, normalState, hoverState, pressedState, disabledState) .attr({ zIndex : 10, height: 15, width: 80, 'text-align': 'center' }) .css({width: '116px'}) .on('click', function() { if( widgetFilter.jaql.filter.members && widgetFilter.jaql.filter.members[0] && widgetFilter.jaql.filter.members[0] == value) { widgetFilter.jaql.filter = { "explicit": false, "multiSelection": true, "all": true } } else { widgetFilter.jaql.filter = { "explicit": true, "multiSelection": true, "members": [ value ] } } widget.refresh(); }) .add(); }) $('.widget-no-result-overlay').css('top', '60px') chart.buttonList = buttonList if( widgetFilter.jaql.filter.members && widgetFilter.jaql.filter.members[0]) filterItem = widgetFilter.jaql.filter.members[0] else filterItem = 'All' currentButton = buttonList.find(el=>el.text.textStr == filterItem) highlightButton(currentButton, chart) }); function highlightButton(clickedButton, chart){ chart.buttonList.forEach(button => { if (button.text.textStr !== clickedButton.text.textStr) { button.setState(0) } else{ button.setState(2) } }) } function runHTTP(jaql) { // Use $internalHttp service if exists const $internalHttp = prism.$injector.has("base.factories.internalHttp") ? prism.$injector.get("base.factories.internalHttp") : null; // Ajax configurations const ajaxConfig = { url: "/api/datasources/" + encodeURIComponent(jaql.datasource.title) + "/jaql", method: "POST", data: JSON.stringify(jaql), contentType: "application/json", dataType: "json", async: false }; // Use $internalHttp service for v8.0.1+ // else use default ajax request const httpPromise = $internalHttp ? $internalHttp(ajaxConfig, true) : $.ajax(ajaxConfig); // Return response return httpPromise.responseJSON; }; function getItemList(widget) { const query = { "datasource": widget.datasource.title, "metadata": [ { "jaql": { "dim": dimension, "filter": { "explicit": false, "multiSelection": true, "all": true } } } ] }; return runHTTP(query); } Note: If there are more items in the column, all buttons may not be displayed as there won't be enough space to display all of them.
- Enable/Disable Pivot columns based on selected filter
Sometimes we need to hide or show few columns in pivot table based on a filter selected. Here is a script to achieve this. Steps: Create a Pivot table Add panels to enable/disable based on selected filter and disable them . It will enable dynamically based on selection. Add below script to widget Update the variable ' ItemList ' with mapping of filter item to name of panels to be enabled. Also update the variable ' filterName ' with name of dashboard filter based on which the columns enable/disable Save the script and refresh dashboard. let filterName = 'Region' let ItemList = { 'South':['County','Gender', 'City'], 'Northeast':['Gender', 'State'], 'Default':['City', 'State'] } widget.on("buildquery", function (se, ev) { let filter = se.dashboard.filters.$$items.find(el=>el.jaql.title == filterName) let filterItem = filter.jaql.filter.members[0] let columnList = ItemList[filterItem] if(columnList == null || columnList == undefined) columnList = ItemList['Default'] $.each(ev.widget.metadata.panels[0].items, function(index, value){ if(value.disabled == true && columnList.includes(value.jaql.title) ) { var newJaql = { jaql : JSON.parse(JSON.stringify(value.jaql)) } ev.query.metadata.push(newJaql) lastIndex = ev.query.metadata.length - 1 ev.query.metadata[lastIndex].disabled = false ev.query.metadata[lastIndex].panel = 'rows' } }) $.each(ev.widget.metadata.panels[1].items, function(index, value){ if(value.disabled == true && columnList.includes(value.jaql.title) ) { var newJaql = { jaql : JSON.parse(JSON.stringify(value.jaql)) } ev.query.metadata.push(newJaql) lastIndex = ev.query.metadata.length - 1 ev.query.metadata[lastIndex].disabled = false ev.query.metadata[lastIndex].panel = 'measures' } }) })
- Widget Refresh Button
In Sisense, widgets will be refreshed when - we reload the dashboard - change any filters - click on refresh button which can be found in small popup when we click on i-button (in widget title bar). Here is a script to add refresh button for a widget. Steps: Create Bar/Column/Line/Area/Pie chart Add below script to widget Save the script and refresh the widget widget.on('processresult', function(se, ev){ ev.result.chart.marginTop= 60 }); var normalState = { fill: '#ffffff', stroke: '#d5d7de', r: 3, style: { color: '#6D6D6D', fontFamily: 'Open Sans', borderWidth : 0 } }, hoverState = { fill: '#f4f4f4', stroke: '#d5d7de', r: 3, style: { color: '#6D6D6D', fontFamily: 'Open Sans', borderWidth : 0 } }, pressedState = { fill: '#f4f4f4', stroke: '#d5d7de', r: 3, style: { color: '#6D6D6D', fontFamily: 'Open Sans', borderWidth : 0 } }, disabledState = { fill: '#ffffff', stroke: '#d5d7de', r: 3, style: { color: '#6D6D6D', fontFamily: 'Open Sans', borderWidth : 0 } }, callback = function () { } widget.on("domready", function(w){ chart = w.chart[0][Object.keys(w.chart[0])[0]].hc chart.renderer.button('↻', 10, 10, callback, normalState, hoverState, pressedState, disabledState) .attr({ zIndex : 10, height: 14, width: 45, 'text-align': 'center' }) .on('click', function() { widget.refresh(); }) .add(); $('.widget-no-result-overlay').css('top', '80px') });
- Buttons to Sort bars/columns
Sorting is very simple in Sisense. But this option is accessible only by chart editors. We can add buttons to sort the chart by name or value using below script so that even viewers can sort the chart. Steps: Create a bar/column/line/area chart Add below script to widget Save the script and refresh the widget widget.on('processresult', function(se, ev){ ev.result.chart.spacing = [60, 20, 20, 20] }); widget.on("domready", function(w, args){ chart = w.chart[0][Object.keys(w.chart[0])[0]].hc chart.renderer.button('Sort by Name - Asc', 10, 10) .attr({ zIndex : 10, height: 15, width: 120, 'text-align': 'center' }) .on('click', function() { widget.metadata.panels[1].items[0].jaql.sort = undefined widget.metadata.panels[0].items[0].jaql.sort = 'asc' widget.refresh(); }) .add(); chart.renderer.button('Sort by Name - Desc', 150, 10) .attr({ zIndex : 10, height: 15, width: 120, 'text-align': 'center' }) .on('click', function() { widget.metadata.panels[1].items[0].jaql.sort = undefined widget.metadata.panels[0].items[0].jaql.sort = 'desc' widget.refresh(); }) .add(); chart.renderer.button('Sort by Value - Asc', 290, 10) .attr({ zIndex : 10, height: 15, width: 120, 'text-align': 'center' }) .on('click', function() { widget.metadata.panels[1].items[0].jaql.sort = 'asc' widget.metadata.panels[0].items[0].jaql.sort = undefined widget.refresh(); }) .add(); chart.renderer.button('Sort by Value - Desc', 430, 10) .attr({ zIndex : 10, height: 15, width: 120, 'text-align': 'center' }) .on('click', function() { widget.metadata.panels[1].items[0].jaql.sort = 'desc' widget.metadata.panels[0].items[0].jaql.sort = undefined widget.refresh(); }) .add(); });
- Blox drop-down with 'All' selection
Here is a solution to create dropdown filter using blox which contains an additional 'All' element to filter all item in the column. Steps: Create new Blox widget and add a dimension under 'items' panel. Add same dimension as a dashboard filter. 2. Add below Blox script. Replace the name ' Region ' in below script with the name of dimension you added in the above step. { "style": "select {border-radius:5px}", "script": "", "title": "", "titleStyle": [ { "display": true } ], "showCarousel": true, "carouselAnimation": { "showButtons": false }, "body": [ { "type": "Container" }, { "type": "ColumnSet", "separator": false, "spacing": "default", "columns": [ { "type": "Column", "spacing": "none", "width": "250px", "items": [ { "type": "Container", "spacing": "none", "width": "220px", "height": "50px", "style": { "color": "black", "padding-top": "10px", "margin-left": "10px", "backgroundColor": "white" }, "items": [ { "type": "Input.ChoiceSet", "id": "data.filters[0].filterJaql.members[0]", "class": "dropdownChoices", "value": "Reseller", "displayType": "compact", "choices": "{choices:Region}", "style": { "color": "#656566", "padding-left": "10px", "margin-left": "10px", "backgroundColor": "grey", "border": "2px solid #aac7e6", "height": "35px", "font-size": "15px" } } ] } ] }, { "type": "Column", "spacing": "none", "width": "175px", "items": [ { "type": "Container", "spacing": "none", "width": "80px", "items": [ { "type": "ActionSet", "margin": "0px", "padding": "0px", "actions": [ { "type": "dropdownFilter", "title": "Apply", "style": { "color": "#ffffff", "padding-left": "15px", "margin-top": "10px", "background-color": "#177be6", "border": "1px solid #cccdcf", "font-weight": "bold", "border-radius": "15px" }, "data": { "filters": [ { "filterName": "Region", "filterJaql": { "explicit": false, "members": [ "" ] } } ] } } ] } ] } ] } ] } ], "actions": [] } 3. Add below widget script. This is to add 'All' in dropdown. widget.on('processresult', function(se, ev){ allObject = [{ "Panel": "Region", //replace region with name of item panel added in step 1 "Value": "All", "Text": "All", "HasValue": true }] ev.result.unshift(allObject) }) 4. Create a custom action ' dropdownFilter ' using below script. if(payload.data.filters[0].filterJaql.members[0] == "All") { filter = { "explicit": false, "multiSelection": true, "all": true } }else { filter = { "explicit": true, "multiSelection": true, "members": [ payload.data.filters[0].filterJaql.members[0] ] } } dashboardFilter = prism.activeDashboard.filters.$$items.find(el => el.jaql.title == payload.data.filters[0].filterName) var filterOptions = { save: true, refresh: true, } dashboardFilter.jaql.filter = filter prism.activeDashboard.filters.update(dashboardFilter, filterOptions)
- Hide widgets based on selected filters
There can be situations where we need to hide few widgets if particular item is selected for a filter. Here is a script to hide widgets based on selected dashboard filters. Steps: Create dashboard Add below script to dashboard Update the variable ' filterName ' with name of dashboard filter based on which the widgets need to be hidden. Update the variable ' itemWidgetMapping ' with mapping of filter item and widgets to be hidden. Widgets specified in 'default' key will be hidden if selected filter item is not defined in this variable. So don't delete the key 'default'. Save the script and refresh the dashboard 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') }); } });
- Disable/Deselect One or More Items in Legend By Default
In Sisense, all legends are enabled by default. Below script can be used to disable one more items in legend when load/refresh the widget (disabling legend means, item will be in gray color and data of disabled item will not displayed in widget. User can enable it by click on it.) Steps: Create a Bar/Column/Area/Pie/Line chart and enable Legend Add below script to widget Update the variable ' disableLegend' with list of items in legend need to be disabled Save the script and refresh widget widget.on('processresult', function(se, ev){ let disableLegend = ['Midwest', 'South'] $.each(ev.result.series, function(index, value){ if(disableLegend.includes(value.name)) value.visible = false }) })