Splunk Search

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

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