cancel
Showing results for 
Search instead for 
Did you mean: 
JeremyFriedel
Sisense Team Member
Sisense Team Member

Modifying Simply Ask Natural Language Query Generated Widgets with Scripting

 

Sisense's Simply Ask feature empowers users to create visualizations instantly by asking natural language questions, simplifying data exploration without needing technical expertise or manual widget configuration. This Natural Language Query (NLQ) capability accelerates data exploration and insights generation without needing to manually create new Sisense widgets through the standard UI for each question or data relationship of interest.
 
8-6nlq_1000x511

However, these automatically generated widgets differ from standard widgets in that they do not trigger typical widget scripting events, which poses a challenge for applying custom modifications. This limitation can hinder the application of standard dashboard and widget scripting customizations directly to these widgets.

Fortunately, it is possible to modify NLQ-generated widgets programmatically by using JavaScript to manipulate the HTML of the fully rendered widgets without relying on Sisense-specific widget scripting events. This approach involves observing changes in the Simply Ask modal DOM and applying custom code when new widgets are rendered.

This article explores how to implement such customizations, providing code examples and notes to help customize NLQ-generated Simply Ask widgets.
 
Understanding the Context

Standard Sisense widgets support a variety of events (such as `beforequery`, `processquery`, `ready`, etc.) that run custom code at specific points in the widget’s query and rendering lifecycle, allowing developers to inject functionality and modifications seamlessly. However, NLQ-generated widgets within the Simply Ask modal do not trigger these events. This means that any scripts using these events will not directly apply to NLQ widgets until they are pinned (added) to the dashboard as standard Sisense widgets.

When an NLQ widget is pinned using the dashboard pin UI button in the Simply Ask modal, it becomes a native Sisense dashboard widget, fully compatible with standard scripting. However, for scenarios where it is desired to apply customizations immediately within the Simply Ask modal for new generated NLQ widgets, without pinning the widget, code-based customization is still possible.
 
Screenshot 2024-09-25 at 3.42.00 PM.png

Solution Overview

To modify NLQ-generated widgets within the Simply Ask modal, JavaScript provides an effective solution through the use of `MutationObserver` and direct manipulation of HTML elements. Specifically, you can:

  • Use JavaScript to observe changes in the DOM Element: By setting up a standard JavaScript `MutationObserver`, you can detect when new widgets are rendered in the Simply Ask modal DOM.
  • Apply custom modifications to the widget's HTML: Once the observer detects a new widget, you can manipulate the HTML elements using standard JavaScript or jQuery, including adjusting the styling.

Implementing the Solution


Setting Up a Mutation Observer

First, the code must detect when a new widget is rendered in the Simply Ask modal. You can do this by observing changes in the modal's main content area using a Javascript MutationObserver.

The code for this MutationObserver can run within the dashboard script, like all dashboard scripts, this will be specific to the current dashboard. This MutationObserver could also exist in plugin code if this customization is designed to run on all dashboards with Simply Ask enabled, without modifying the dashboard script for each dashboard. This flexibility allows custom modifications to be reusable across different dashboards by placing the `MutationObserver` in plugin code or specific to one dashboard by placing it in that dashboard's script.
 

 

 

 

dashboard.on('domready', function () {
    // Listen for clicks on the Simply Ask button
    $('button.nlq-main-button').click(function () {
        setTimeout(function () {
            // Select the widget container area of the Simply Ask modal
            const elementToObserve = $('div.nlq-widget__main-content')[0];

            // Create a MutationObserver instance
            const observer = new MutationObserver(function () {
                // Call your custom function when a change in DOM is detected
                customizeNLQWidget();
            });

            // Start observing the DOM for mutations
            observer.observe(elementToObserve, { subtree: true, childList: true });
        }, 1000); // Delay to ensure the modal is fully rendered
    });
});
​

 

 



 

Explanation:

 

  • Event Listener: The script runs on the click event using an event listener on the Simply Ask UI button (`nlq-main-button`) which opens the Simply Ask NLQ modal.
  • Delay with setTimeout: A short delay ensures that the Simply Ask modal is fully rendered before setting up the observer.
  • MutationObserver: Observes the NLQ-generated widget HTML element using the selector `nlq-widget__main-content` for any changes, specifically when new child nodes are added (i.e., when a new widget is generated on an NLQ query).
  • subtree: Ensures that mutations to child elements of the main content area are also detected.
  • childList: Watches for changes in the direct children of the observed element (e.g., when new widgets are added).
  • Callback Function: When a mutation is observed, the `customizeNLQWidget` function is called to apply custom modifications. This can be any function or series of functions.

 

Example Customization Function

 

The function that applies the desired modifications to the NLQ widget can be defined with any valid JavaScript. In this example, the function will modify the pivot header cells' styling.
 

 

 

 

const customizeNLQWidget = () => {
    const NLQ_MAIN_CONTENT_SELECTOR = 'div.nlq-widget__main-content';
    const HEADER_CELL_SELECTOR = 'td.table-grid__cell--row-0';

    // Apply CSS styles to the pivot table header cells
    $(`${NLQ_MAIN_CONTENT_SELECTOR} ${HEADER_CELL_SELECTOR}`).css({
        'background-color': 'blue',
        'color': 'white',
    });
};
​

 

 



 

Explanation:

 

  • Selectors: The function targets the pivot table header cells within the NLQ modal. These can be any valid CSS selector, in this example they are:
  • `NLQ_MAIN_CONTENT_SELECTOR`: Selects the main content area of the NLQ widget.
  • `HEADER_CELL_SELECTOR`: Selects the header cells of a pivot table type widget.
  • CSS Styling: Applies custom CSS styling to change the background color to blue and the text color to white.

Screenshot 2024-09-25 at 3.27.53 PM.png

 

Combining the Code

 

For clarity, here's the combined code that brings together the observer setup and the example custom code customization function:

 

 

 

 

 

dashboard.on('domready', function () {
    $('button.nlq-main-button').click(function () {
        setTimeout(function () {
            const elementToObserve = $('div.nlq-widget__main-content')[0];
            const observer = new MutationObserver(function () {
                customizeNLQWidget();
            });
            observer.observe(elementToObserve, { subtree: true, childList: true });
        }, 1000);
    });
});

const customizeNLQWidget = () => {
    const NLQ_MAIN_CONTENT_SELECTOR = 'div.nlq-widget__main-content';
    const HEADER_CELL_SELECTOR = 'td.table-grid__cell--row-0';

    $(`${NLQ_MAIN_CONTENT_SELECTOR} ${HEADER_CELL_SELECTOR}`).css({
        'background-color': 'blue',
        'color': 'white',
    });
};

 

 

 

 

Customization Examples

 

The example above modifies the header cells of a pivot table. However, you can extend the `customizeNLQWidget` function to perform various other customizations, such as:

 

  • Adding Icons or Indicators: Inject visual cues for critical data points or thresholds directly into cells.
  • Conditional Formatting: Automatically highlight data cells based on values (e.g., flagging negative values in red).
  • Interactive Elements: Add clickable elements, like links or buttons, to enable dynamic user interactions, such as drilling into specific data.
  • Content Modification: Alter or append units, currency symbols, or other data-specific indicators to ensure clarity and consistency in data presentation.
Example: Conditional Formatting Based on Values
 

 

 

 

const customizeNLQWidget = () => {
    const NLQ_MAIN_CONTENT_SELECTOR = 'div.nlq-widget__main-content';
    const DATA_CELL_SELECTOR = 'td.table-grid__cell--data';

    $(`${NLQ_MAIN_CONTENT_SELECTOR} ${DATA_CELL_SELECTOR}`).each(function () {
        const cellValue = parseFloat($(this).text());
        if (cellValue < 0) {
            $(this).css('color', 'red');
        } else if (cellValue > 0) {
            $(this).css('color', 'green');
        }
    });
};
​

 

 



 

Explanation:

 

  • Data Cells Selector: Targets all data cells in the pivot table.
  • Value Parsing: Converts the cell text to a numeric value.
  • Conditional Styling: Applies red color to negative values and green color to positive values.
Considerations and Best Practices

 

  • Scope: Ensure your selectors are specific enough to avoid unintended modifications to other parts of the dashboard.
  • Compatibility Testing: Regularly test your customizations across different Sisense versions to ensure that changes in CSS classes or HTML structures don't break the functionality.
  • CSS Class Updates: CSS class names can change between Sisense versions; keeping CSS selector strings as variables allows for easy updating if needed.
Conclusion

 

While NLQ-generated widgets in Sisense's Simply Ask feature do not support standard widget scripting events, the ability to observe DOM changes and manipulate HTML allows for extensive customizations. With JavaScript, you can enhance widget appearance, add interactive functionality, and more—all within the Simply Ask modal, providing a tailored user experience.

 

This approach allows maintaining consistency in dashboards and provides a more customizable experience for users interacting with NLQ-generated visualizations.

 

Further Reading

 

Rate this article:
Version history
Last update:
‎09-26-2024 12:54 PM
Updated by:
Contributors