Splunk Search

What is my best approach to creating a expand / collapse feature on my dashboard?

bmendez0428
Explorer

I've only been "Splunking" for about a month now so I am pretty new to this.

I want to add a button to expand certain groups with the same name in the application name column. For example, my first 4 rows on my dashboard table are of the same application name. How can I group them all to the first row? And so on...After clicking the button I would like the row to expand/close by group. I'm not sure what the best approach is. I also attached the front end photo of the dashboard that I have to modify.

CSS:

    <style>
        .custom-text-value {
            font-size: 16px;
            margin: 55px auto;
            text-align: center;
            font-weight: bold;
            color: rgb(85, 85, 85);
        }
        .custom-text-value:before {
            font-family: "Splunk Icons";
            font-style: normal;
            font-weight: normal;
            text-decoration: inherit;
            font-size: 110%;
        }

        .custom-result-value {
            font-size: 16px;
            margin: 55px auto;
            text-align: center;
            font-weight: bold;
            color: rgb(85, 85, 85);
        }
        .custom-result-value:before {
            font-family: "Splunk Icons";
            font-style: normal;
            font-weight: normal;
            text-decoration: inherit;
            font-size: 110%;
        }
        .severe.custom-result-value:before {
            content: "\2297";
        }
        .severe.custom-result-value {
            color: rgb(217, 63, 60);
        }
        .high.custom-result-value {
            color: rgb(245, 143, 57);
        }
        .high.custom-result-value:before {
            content: "\ECD4";
        }
        .elevated.custom-result-value {
            color: rgb(247, 188, 56);
        }
        .elevated.custom-result-value:before {
            content: "\26A0";
        }
        .low.custom-result-value {
            color: rgb(101, 166, 55);
        }
        .low.custom-result-value:before {
            content: "\ECD3";
        }
        .guarded.custom-result-value {
            color: rgb(109, 183, 198);
        }
        .guarded.custom-result-value:before {
            content: "\0049";
        }
        .custom-result-value.icon-only {
            font-size: 90px;
        }

        td.icon {
            text-align: center;
        }
        td.icon i {
            font-size: 30px;
            text-shadow: 1px 1px #aaa;
        }
        td.icon .severe {

            color: red;
        }
        td.icon .elevated {
            color: yellow;
        }
        td.icon .low {
            color: #006400;
        }        
        .btn edit-export{
            display: none;
        }        
    </style>

JS+Search:

require([
    "splunkjs/mvc",
    "splunkjs/mvc/utils",
    "splunkjs/mvc/tokenutils",
    "underscore",
    "jquery",
    "splunkjs/mvc/simplexml",
    "splunkjs/mvc/layoutview",
    "splunkjs/mvc/simplexml/dashboardview",
    "splunkjs/mvc/simplexml/dashboard/panelref",
    "splunkjs/mvc/simplexml/element/chart",
    "splunkjs/mvc/simplexml/element/event",
    "splunkjs/mvc/simplexml/element/html",
    "splunkjs/mvc/simplexml/element/list",
    "splunkjs/mvc/simplexml/element/map",
    "splunkjs/mvc/simplexml/element/single",
    "splunkjs/mvc/simplexml/element/table",
    "splunkjs/mvc/simplexml/element/visualization",
    "splunkjs/mvc/simpleform/formutils",
    "splunkjs/mvc/simplexml/eventhandler",
    "splunkjs/mvc/simplexml/searcheventhandler",
    "splunkjs/mvc/simpleform/input/dropdown",
    "splunkjs/mvc/simpleform/input/radiogroup",
    "splunkjs/mvc/simpleform/input/linklist",
    "splunkjs/mvc/simpleform/input/multiselect",
    "splunkjs/mvc/simpleform/input/checkboxgroup",
    "splunkjs/mvc/simpleform/input/text",
    "splunkjs/mvc/simpleform/input/timerange",
    "splunkjs/mvc/simpleform/input/submit",
    "splunkjs/mvc/searchmanager",
    "splunkjs/mvc/savedsearchmanager",
    "splunkjs/mvc/postprocessmanager",
    "splunkjs/mvc/simplexml/urltokenmodel",
    "splunkjs/mvc/tableview",
    "splunkjs/ready!"   
    // Add comma-separated libraries and modules manually here, for example:
    // ..."splunkjs/mvc/simplexml/urltokenmodel",
    // "splunkjs/mvc/tokenforwarder"
    ],
    function(
        mvc,
        utils,
        TokenUtils,
        _,
        $,
        DashboardController,
        LayoutView,
        Dashboard,
        PanelRef,
        ChartElement,
        EventElement,
        HtmlElement,
        ListElement,
        MapElement,
        SingleElement,
        TableElement,
        VisualizationElement,
        FormUtils,
        EventHandler,
        SearchEventHandler,
        DropdownInput,
        RadioGroupInput,
        LinkListInput,
        MultiSelectInput,
        CheckboxGroupInput,
        TextInput,
        TimeRangeInput,
        SubmitButton,
        SearchManager,
        SavedSearchManager,
        PostProcessManager,
        UrlTokenModel

        // Add comma-separated parameter names here, for example:
        // ...UrlTokenModel,
        // TokenForwarder
        ) {

        var pageLoading = true;


        //
        // TOKENS
        //

        // Create token namespaces
        var urlTokenModel = new UrlTokenModel();
        mvc.Components.registerInstance('url', urlTokenModel);
        var defaultTokenModel = mvc.Components.getInstance('default', {create: true});
        var submittedTokenModel = mvc.Components.getInstance('submitted', {create: true});

        urlTokenModel.on('url:navigate', function() {
            defaultTokenModel.set(urlTokenModel.toJSON());
            if (!_.isEmpty(urlTokenModel.toJSON()) && !_.all(urlTokenModel.toJSON(), _.isUndefined)) {
                submitTokens();
            } else {
                submittedTokenModel.clear();
            }
        });

        // Initialize tokens
        defaultTokenModel.set(urlTokenModel.toJSON());

        function submitTokens() {
            // Copy the contents of the defaultTokenModel to the submittedTokenModel and urlTokenModel
            FormUtils.submitForm({ replaceState: pageLoading });
        }

        function setToken(name, value) {
            defaultTokenModel.set(name, value);
            submittedTokenModel.set(name, value);
        }

        function unsetToken(name) {
            defaultTokenModel.unset(name);
            submittedTokenModel.unset(name);
        }

        //
        // SEARCH MANAGERS
        //
        //Can confirm that the search query works.
    var search1 = new SearchManager({
            "id": "search1",
            "sample_ratio": null,
            "status_buckets": 0,
            "earliest_time": "-1h@h",
//            "earliest_time": "rt-3h",
            "search": "index=\"TEM_Availability_Dashboard\" |eval displayValue=case(TestResult_Value == \"PASSED\", \"low\", TestResult_Value == \"FAILED\", \"severe\") \
            |dedup Application_Name, TestCase_Value, SwimLane_Value, TestResult_Value |sort Application_Name, TestCase_Value \
|eval QA1 = case(like(TestResult_Value,\"PASSED\") AND SwimLane_Value==\"QA1\",\"low\",like(TestResult_Value,\"FAILED\") AND SwimLane_Value==\"QA1\",\"severe\", like(TestResult_Value,\"NA\") AND SwimLane_Value==\"QA1\",\"NA\") \
|eval QA2 = case(like(TestResult_Value,\"PASSED\") AND SwimLane_Value==\"QA2\",\"low\",like(TestResult_Value,\"FAILED\") AND SwimLane_Value==\"QA2\",\"severe\", like(TestResult_Value,\"NA\") AND SwimLane_Value==\"QA2\",\"NA\") \
|eval QA3 = case(like(TestResult_Value,\"PASSED\") AND SwimLane_Value==\"QA3\",\"low\",like(TestResult_Value,\"FAILED\") AND SwimLane_Value==\"QA3\",\"severe\", like(TestResult_Value,\"NA\") AND SwimLane_Value==\"QA3\",\"NA\") \
|eval QA4 = case(like(TestResult_Value,\"PASSED\") AND SwimLane_Value==\"QA4\",\"low\",like(TestResult_Value,\"FAILED\") AND SwimLane_Value==\"QA4\",\"severe\", like(TestResult_Value,\"NA\") AND SwimLane_Value==\"QA4\",\"NA\") \
|eval QA5 = case(like(TestResult_Value,\"PASSED\") AND SwimLane_Value==\"QA5\",\"low\",like(TestResult_Value,\"FAILED\") AND SwimLane_Value==\"QA5\",\"severe\", like(TestResult_Value,\"NA\") AND SwimLane_Value==\"QA5\",\"NA\") \
|eval QA6 = case(like(TestResult_Value,\"PASSED\") AND SwimLane_Value==\"QA6\",\"low\",like(TestResult_Value,\"FAILED\") AND SwimLane_Value==\"QA6\",\"severe\", like(TestResult_Value,\"NA\") AND SwimLane_Value==\"QA6\",\"NA\") \
|eval QA7 = case(like(TestResult_Value,\"PASSED\") AND SwimLane_Value==\"QA7\",\"low\",like(TestResult_Value,\"FAILED\") AND SwimLane_Value==\"QA7\",\"severe\", like(TestResult_Value,\"NA\") AND SwimLane_Value==\"QA7\",\"NA\") \
|eval STG = case(like(TestResult_Value,\"PASSED\") AND SwimLane_Value==\"STG\",\"low\",like(TestResult_Value,\"FAILED\") AND SwimLane_Value==\"STG\",\"severe\", like(TestResult_Value,\"NA\") AND SwimLane_Value==\"STG\",\"NA\")  \
|eval STG2 = case(like(TestResult_Value,\"PASSED\") AND SwimLane_Value==\"STG2\",\"low\",like(TestResult_Value,\"FAILED\") AND SwimLane_Value==\"STG2\",\"severe\", like(TestResult_Value,\"NA\") AND SwimLane_Value==\"STG2\",\"NA\") \
|eval pve = case(like(TestResult_Value,\"PASSED\") AND SwimLane_Value==\"pve\",\"low\",like(TestResult_Value,\"FAILED\") AND SwimLane_Value==\"pve\",\"severe\", like(TestResult_Value,\"NA\") AND SwimLane_Value==\"pve\",\"NA\") \
|table Application_Name, TestCase_Value, QA1,QA2,QA3,QA4,QA5,QA6,QA7,STG,STG2,pve |rename TestCase_Value AS \"Test Case\" |rename Application_Name AS \"Application Name\" \
|stats values(QA1) as QA1, values(QA2) as QA2,values(QA3) as QA3,values(QA4) as QA4,values(QA5) as QA5,values(QA6) as QA6,values(QA7) as QA7,values(STG) as STG,values(STG2) as STG2,values(pve) as pve by \"Application Name\", \"Test Case\" \
|eval QA1 = if((mvjoin(QA1, \",\") == \"low,severe\" OR mvjoin(QA1, \",\") == \"severe,low\"), \"elevated\", QA1) \
|eval QA2 = if((mvjoin(QA2, \",\") == \"low,severe\" OR mvjoin(QA2, \",\") == \"severe,low\"), \"elevated\", QA2) \
|eval QA4 = if((mvjoin(QA4, \",\") == \"low,severe\" OR mvjoin(QA4, \",\") == \"severe,low\"), \"elevated\", QA4) \
|eval QA5 = if((mvjoin(QA5, \",\") == \"low,severe\" OR mvjoin(QA5, \",\") == \"severe,low\"), \"elevated\", QA5) \
|eval QA6 = if((mvjoin(QA6, \",\") == \"low,severe\" OR mvjoin(QA6, \",\") == \"severe,low\"), \"elevated\", QA6) \
|eval QA7 = if((mvjoin(QA7, \",\") == \"low,severe\" OR mvjoin(QA7, \",\") == \"severe,low\"), \"elevated\", QA7) \
|eval STG = if((mvjoin(STG, \",\") == \"low,severe\" OR mvjoin(STG, \",\") == \"severe,low\"), \"elevated\", STG) \
|eval STG2 = if((mvjoin(STG2, \",\") == \"low,severe\" OR mvjoin(STG2, \",\") == \"severe,low\"), \"elevated\", STG2) \
|eval pve = if((mvjoin(pve, \",\") == \"low,severe\" OR mvjoin(pve, \",\") == \"severe, low\"), \"elevated\", pve) \
|eval QA3 = if((mvjoin(QA3, \",\") == \"low,severe\" OR mvjoin(QA3, \",\") == \"severe,low\"), \"elevated\", QA3)",
            "cancelOnUnload": true,
            "latest_time": "now",
//            "latest_time": "rt",
            "app": utils.getCurrentApp(),
            "auto_cancel": 90,
            "preview": true,
            "tokenDependencies": {
            },
            "runWhenTimeIsUndefined": false
        }, {tokens: true, tokenNamespace: "submitted"});


        //
        // SPLUNK LAYOUT
        //

        $('header').remove();
        new LayoutView({"hideSplunkBar": false, "hideAppBar": false, "hideChrome": false})
            .render()
            .getContainerElement()
            .appendChild($('.dashboard-body')[0]);

        //
        // DASHBOARD EDITOR
        //

        new Dashboard({
            id: 'dashboard',
            el: $('.dashboard-body'),
            showTitle: true,
            editable: true
        }, {tokens: true}).render();


        //
        // VIEWS: VISUALIZATION ELEMENTS
        //

        var element1 = new TableElement({
            "id": "element1",
            "count": 20,
            "drilldown": "cell",
            drilldownRedirect: true,
            "managerid": "search1",
            "el": $('#element1')
        }, {tokens: true, tokenNamespace: "submitted"}).render();

        element1.on("click", function(e) {
            // Bypass the default behavior
            e.preventDefault();
            window.open('tem_search_ui_html?appName=' + e.data["row.Application Name"] + '&testCase=' + e.data["row.Test Case"] +  '&swimLane=' + e.data["click.name2"] +  '&earliest=' + e.data.earliest + '&latest=' + e.data.latest, "_parent");

            // Displays a data object in the console
            console.log("Clicked the table:", e.data);
            //console.log("Clicked the table:", e.data["click.value"]);
            //console.log("Clicked the table:", e.data["click.value2"]);
        });

        // Initialize time tokens to default
        if (!defaultTokenModel.has('earliest') && !defaultTokenModel.has('latest')) {
            defaultTokenModel.set({ earliest: 'rt-1h', latest: 'rt' });
        }

        // Define icons for the custom table cell
        var ICONS = {
            severe: "alert-circle",
            elevated: "alert",
            low: "check-circle"
        };
        var colName = "";

    mvc.Components.get('element1').getVisualization(function(tableView) {
        setTimeout(function() {
            tableView.on('rendered', function() {

                $("#element1 table thead th").removeClass("sorts").removeAttr("data-sort-key");
                 // Populate dictionary with values from table
                 var tableRows = tableView.$el.find('tbody').children();

                 var tableHeaders = tableView.$el.find('th').children();

                for (var iRow = 0, row; row = tableRows[iRow]; iRow++) {

                    for (var jCol = 0, col; col = row.cells[jCol]; jCol++) {

                        switch(jCol) {
                          case 2:  
                            colName = "QA1";
                            if (iRow == 0){
                                tableHeaders.eq(jCol).html("<a href=temdashboard_html?SwimLane_Value=QA1&earliest=-24h@h&latest=now target=_blank>QA1</a>");
                            }
                            break;
                          case 3:
                            colName = "QA2";
                            if (iRow == 0){
                                tableHeaders.eq(jCol).html("<a href=temdashboard_html?SwimLane_Value=QA2&earliest=-24h@h&latest=now target=_blank>QA2</a>");
                            }
                            break;

                          case 4:
                            colName = "QA3";
                            if (iRow == 0){
                                tableHeaders.eq(jCol).html("<a href=temdashboard_html?SwimLane_Value=QA3&earliest=-24h@h&latest=now target=_blank>QA3</a>");
                            }
                            break;

                          case 5:
                            colName = "QA4";
                            if (iRow == 0){
                                tableHeaders.eq(jCol).html("<a href=temdashboard_html?SwimLane_Value=QA4&earliest=-24h@h&latest=now target=_blank>QA4</a>");
                            }
                            break;

                          case 6:
                            colName = "QA5";
                            if (iRow == 0){
                                tableHeaders.eq(jCol).html("<a href=temdashboard_html?SwimLane_Value=QA5&earliest=-24h@h&latest=now target=_blank>QA5</a>");
                            }
                            break;

                          case 7:
                            colName = "QA6";
                            if (iRow == 0){
                                tableHeaders.eq(jCol).html("<a href=temdashboard_html?SwimLane_Value=QA6&earliest=-24h@h&latest=now target=_blank>QA6</a>");
                            }
                            break;

                          case 8:
                            colName = "QA7";
                            if (iRow == 0){
                                tableHeaders.eq(jCol).html("<a href=temdashboard_html?SwimLane_Value=QA7&earliest=-24h@h&latest=now target=_blank>QA7</a>");
                            }
                            break;

                          case 9:
                            colName = "STG";
                            if (iRow == 0){
                                tableHeaders.eq(jCol).html("<a href=temdashboard_html?SwimLane_Value=STG&earliest=-24h@h&latest=now target=_blank>STG</a>");
                            }
                            break;

                          case 10:
                            colName = "STG2";
                            if (iRow == 0){
                                tableHeaders.eq(jCol).html("<a href=temdashboard_html?SwimLane_Value=STG2&earliest=-24h@h&latest=now target=_blank>STG2</a>");
                            }
                            break;

                          case 11:
                            colName = "PVE";
                            if(iRow == 0){
                                tableHeaders.eq(jCol).html("<a href=temdashboard_html?SwimLane_Value=pve&earliest=-24h@h&latest=now target=_blank>PVE</a>");
                            }

                        }
                        var value = col.firstChild.data;
                        col.field === "colName";
                        var icon = "";
                        var found = false;
                        if(ICONS.hasOwnProperty(value)) {
                            icon = ICONS[value];
                            found = true;
                        }

                        if (found){

                            //$(col).addClass("icon").html(_.template('<a href="tem_search_ui_html" target="_parent"><i class="icon-<%-icon%>  <%-colName%>"></i></a>', {
                            $(col).addClass("icon").html(_.template('<i class="icon-<%-icon%>  <%-colName%>"></i>', {
                             icon: icon,
                             colName: value
                            }
                            ));
                        }
                        ($('td:contains("NA")').css("text-align","center"));
                   }  
                }            
                 // Update table display
                 tableView.render();
            })
        }, 100);
    });


        submitTokens();

        setTimeout("location.reload();", 600 * 1000);

        //
        // DASHBOARD READY
        //

        DashboardController.ready();
        pageLoading = false;

    }
);

HTML:

<header>
    <a aria-label="Screen reader users, click here to skip the navigation bar" class="navSkip" href="#navSkip" tabIndex="1">Skip Navigation ></a>
    <div class="header splunk-header">
            <div id="placeholder-splunk-bar">
                <a href="{{SPLUNKWEB_URL_PREFIX}}/app/launcher/home" class="brand" title="splunk > listen to your data">splunk<strong>></strong></a>
            </div>
                <div id="placeholder-app-bar"></div>
    </div>
    <a id="navSkip"></a>
</header>
<div class="dashboard-body container-fluid main-section-body" data-role="main">
    <div class="dashboard-header clearfix">
        <h2>TEM Availability Dashboard - Current hour </h2>
    </div>
  <div><input type="button" onclick="location.href='tem_search_ui_html?form.sTime.earliest=-24h%40h&form.sTime.latest=now';" value="Go to Search Screen" />
        <input type="button" onclick="location.href='http://spwaitbussvs/ts/itbs/tem/Shared%20Documents1/Automation/QA%20Availability%20Dashboard%20issue%20tracker.xlsx';" value="Issue log" />
        <input type="button" onclick="location.href='http://spwaitbussvs/ts/itbs/tem/Shared%20Documents1/Automation/TEM%20QA%20Availability%20Dashboard%20FAQ.docx';" value="FAQ" />
        <p></p>
  </div>

    <div id="row1" class="dashboard-row dashboard-row1">
        <div id="panel1" class="dashboard-cell" style="width: 100%;">
            <div class="dashboard-panel clearfix">

                <div class="panel-element-row">
                    <div id="element1" class="dashboard-element table" style="width: 100%">
                        <div class="panel-body"></div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <div style ="padding-top: 2%">
        <P>
        <p> 
        <p><font color="#008000">Green</font>:  Test case passed &nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp <font color="#FFFF00>">Yellow</font>    -   At least 1 step failed&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp <font color="#FF0000>">Red</font>: All test steps failed &nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp Blank: No test run. See TEM team for question(s) &nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp&nbsp NA: Test intentionally not run
    </div>
</div>
0 Karma
Get Updates on the Splunk Community!

Index This | I am a number, but when you add ‘G’ to me, I go away. What number am I?

March 2024 Edition Hayyy Splunk Education Enthusiasts and the Eternally Curious!  We’re back with another ...

What’s New in Splunk App for PCI Compliance 5.3.1?

The Splunk App for PCI Compliance allows customers to extend the power of their existing Splunk solution with ...

Extending Observability Content to Splunk Cloud

Register to join us !   In this Extending Observability Content to Splunk Cloud Tech Talk, you'll see how to ...