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            <font color="#FFFF00>">Yellow</font> - At least 1 step failed           <font color="#FF0000>">Red</font>: All test steps failed            Blank: No test run. See TEM team for question(s)            NA: Test intentionally not run
</div>
</div>