All Apps and Add-ons
Highlighted

Sideview button action to refresh page

Path Finder

There's probably a quick way to do this with a customBehavior, but all those warnings on the docs for customBehavior make me want to ask first before trying it. I've followed instructions from:

https://answers.splunk.com/answers/68392/trigger-shell-script-from-dashboard-button.html

and I've got a nifty dashboard that will call a python script to take some action, but when I click the button, there's no refresh of the page that would indicate to the user that an action was taken. I do have the button appending to an outputcsv which records the action and displays it at the bottom of the page in another table. The page will eventually refresh to show a new entry in a table, but I'd like the button to immediately refresh the page too. This way users of the page don't start clicking >1 time.

Highlighted

Re: Sideview button action to refresh page

SplunkTrust
SplunkTrust

Let me give you two ways to do it.

1) CustomBehavior!
The most broadly useful technique to do this is to create another customBehavior further upstream in the view, whose job is to leave a hook to itself, for later that you'll use to push downstream and re-dispatch the main search(es).

So higher up in the page, typically just after the main Button module if there is one, you would have

<module name="CustomBehavior">
  <param name="customBehavior">hookForReloadingPage</param>
  ... make sure everything you need to redispatch and refresh is downstream from this module...

Here's the definition. We dont even really define any behavior, we just leave a global reference to the module object itself for later. (Yes globals are evil and window._reloader is not going to win you any js awards, but you'll be fine. )

Sideview.utils.declareCustomBehavior("hookForReloadingPage", function(module) {
    if (window._reloader) {
        console.error("hookForReloadingPage - There can be only one.");
        return false;
    }
    window._reloader = module;
});

By the time any searches are dispatched on the page, that window._reloader will have been defined long ago, so whenever you need to reload the main searches to show changes, just call from the JS:

window._reloader.pushContextToChildren()

Of course, the big question becomes, exactly when is it safe to call pushContextToChildren? The UI framework is better than you might think about cancelling and aborting searches once they seem to be superceded by subsequent interaction, and if you dont think about this, it's not hard to reload the page before or even at the exact time you're dispatching your "updating" search, setting up a race.

My advice is if you have an existing CustomBehavior that is running when the button is clicked to do something, implement this inside that existing customBehavior:

var PCTCReference = module.pushContextToChildren.bind(module);
module.pushContextToChildren = function() {
        PCTCReference();
        window._reloader.pushContextToChildren();
    }

It looks a little insane, and it looks like a race, but the "updating" search will definitely get dispatched here before the main search reload is triggered. And I believe that "updating" search will be able to run to completion unperturbed while the upstream "main" search(es) redispatch.


2) the Gate module

There is another way, and that's to use the Gate module. If you weren't already using a customBehavior in your view, I'd say go with the Gate.

In this scenario, this Gate module takes the place of our reloader customBehavior

<module name="Gate">
  <param name="id">reloader</param>
  ... everything you need to reload/redispatch is downstream from this Gate...

And then further downstream your button and search etc would look like this:

<module name="Button">
  <param name="label">update</param>
  <module name="Search"> | inputlookup | EvalStatementsToUpdateThings | outputlookup</param>

     <!-- customBehavior is sometimes useful to just sneak in with only requiresDispatch
            so as to force a dispatch at a particular point wihtout an unwanted visible module 
            like JobProgressIndicator being there.  -->
    <module name="CustomBehavior">
      <param name="requiresDispatch">True</param>

       <module name="Gate">
         <param name="to">reloader</param>
       </module>
    </module>

End result is the same. On button click the search runs, once it's dispatched and running the context push moves down to the Gate module, which reaches up to the top of the page and starts a push from up there. Terrifying circular push ftw!

Highlighted

Re: Sideview button action to refresh page

Path Finder

I'm thinking the Gate looks like the easier way. But, it looks like I'm still missing something. Here's what my view looks like:

  <label>Blacklist Clearing Dashboard</label>
  <module name="AccountBar" layoutPanel="appHeader"/>
  <module name="AppBar" layoutPanel="appHeader"/>
  <module name="SideviewUtils" layoutPanel="appHeader"/>
  <module name="Message" layoutPanel="messaging">
    <param name="filter">*</param>
    <param name="clearOnJobDispatch">False</param>
    <param name="maxSize">2</param>
  </module>
  <module name="HTML" layoutPanel="viewHeader">
    <param name="html">&lt;h1&gt;Blacklist Remove Dashboard&lt;/h1&gt;</param>
  </module>
  <module name="Search" layoutPanel="panel_row1_col1" autoRun="True">
    <param name="search">forstuff | table some things | eval actions="PLACEHOLDER"</param>
    <param name="earliest">-34m</param>
    <module name="HTML">
      <param name="html">&lt;H2&gt;Recent Blacklist Adds</param>
    </module>
    <module name="Gate">
      <param name="id">reloader</param>
      <module name="Pager">
        <module name="Table">
          <module name="Button" group="row.fields.actions">
            <param name="groupLabel">row.fields.actions</param>
            <param name="allowAutoSubmit">False</param>
            <param name="label">Remove from Blacklist</param>
            <module name="Search">
              <param name="search">search forstuff | table some things | outputcsv a.csv</param>
              <module name="CustomBehavior">
                <param name="requiresDispatch">True</param>
                <module name="Gate">
                  <param name="to">reloader</param>
                </module>
              </module>
            </module>
          </module>
        </module>
      </module>
    </module>
  </module>
  <module name="Search" layoutPanel="panel_row2_col1" autoRun="True">
    <param name="search">| inputcsv a.csv events=true | table some things</param>
    <module name="HTML">
      <param name="html">&lt;H2&gt;Recent Blacklist Clears&lt;/H2&gt;</param>
    </module>
    <module name="Pager">
      <module name="Table"/>
    </module>
  </module>

Did the Gate bits go in the right place? They don't seem to have, because the page sort of locks up when I click the button.

0 Karma
Highlighted

Re: Sideview button action to refresh page

SplunkTrust
SplunkTrust

Hm. The dispatching module right there is the Pager, and the Gate being above it, this should be the right place. Curious what you mean by the page freezing. Are there any JS errors showing up in the error console?

Any search syntax errors not coming back in the UI for any reason?

And if nothing leaps out there, what does happen if you move the Gate just upstream from the Search module?

0 Karma
Highlighted

Re: Sideview button action to refresh page

Path Finder

Yeah, I'm probably in over my head on this one. Error console? There's no error that shows up anywhere, but the top Search, which returns more than one Page of data, will let me interact with the the Pager module, but the data doesn't change until it's manually refreshed. It looks "frozen". The Button action still works.

I tried moving the first Gate upstream of the first Search, and that caused the panel to not draw.

0 Karma
Highlighted

Re: Sideview button action to refresh page

SplunkTrust
SplunkTrust

Are you remembering to shift-reload or explicitly clear cache? Splunk is notoriously grabby as far as cacheing static files including application.js.

Also where the error console is depends on your browser. In Chrome it's generally Tools > Developer Tools > Console. IN Firefox try " > Developer > Web Console".

0 Karma
Highlighted

Re: Sideview button action to refresh page

Path Finder

Started Chrome fresh and deleted cache before connecting to my server. Error console is giving me:
Gate module with a 'to' param (Gate1700) is ignoring a call to hideDescendants
ncaught RangeError: Maximum call stack size exceeded(anonymous function) @ modules-211d52e….min.js:178(anonymous function) @ modules-211d52e….min.js:270Splunk.Module.$.klass.withEachChild @ modules-211d52e….min.js:265Splunk.Module.$.klass.withEachDescendant @ modules-211d52e….min.js:269(anonymous function) @ modules-211d52e….min.js:271Splunk.Module.$.klass.withEachChild @ modules-211d52e….min.js:265Splunk.Module.$.klass.withEachDescendant @ modules-211d52e….min.js:269(anonymous function) @ modules-211d52e….min.js:271Splunk.Module.$.klass.withEachChild @ modules-211d52e….min.js:265Splunk.Module.$.klass.withEachDescendant @ modules-211d52e….min.js:269
6modules-211d52e….min.js:442 XHR clear for takeoff for module Pager02_0

The Gate module is back in the original place, just after the first Search.

0 Karma
Highlighted

Re: Sideview button action to refresh page

SplunkTrust
SplunkTrust

Oh goodness. yes. Button will block the push, but nothing blocks the withEachDescendant call. Ow. OK use the customBehavior approach!

0 Karma
Highlighted

Re: Sideview button action to refresh page

Path Finder

Oh boy! Gate looked so much easier. I'm still a bit confused by CustomBehavior. I've yet to find much of a tutorial. I sort of get that I need to put some part into a file, as it can't all be done in the Sideview Editor (or can it?). I'll go research some more.

0 Karma
Highlighted

Re: Sideview button action to refresh page

Path Finder

So, the code to do a refresh was scaring me. Not being a javascript programmer, and not able to see exactly what it was, I decided instead to go with an alert() after reading the post at https://answers.splunk.com/answers/99676/how-is-customebehavior-module-working-model-is.html

Since this is all in my search app, I created an application.js in etc/apps/search/appserver/static with something simple:
if (typeof(Sideview)!="undefined") {

    Sideview.utils.declareCustomBehavior("alertBlacklist", function(module) {
        module.onContextChange = function() {
            alert("Request submitted.  Please refresh page to update recent clears table.");
        }
    });
}

Then I called this in the Search right after the Button.

This should be enough for what I was doing. It takes a little time for my back-end python script to run and "unblacklist" a WiFi client, so an instant refresh wouldn't show anything anyway.

Many thanks Nick for the help on this one. I'm loving the Sideview Editor, and am looking forward to making a lot more dashboards with it!

0 Karma
Speak Up for Splunk Careers!

We want to better understand the impact Splunk experience and expertise has has on individuals' careers, and help highlight the growing demand for Splunk skills.