Dashboards & Visualizations

Embedding HTML dashboard into XML dashboard

pgadhari
Builder

I have a HTML dashboard which I created using Images. Now, I want to show that dashboard in my XML dashboard in the same app, where my XML dashboard is there.

My XML dashboard has 3 tabs, and I have to create the 4th tab (using tabs.js) and want to show the HTML dashboard in that. How can I achieve this ? Attaching the screenshot for the reference.

alt text

Basically, my HTML dashboard is created based on my below question asked :

https://answers.splunk.com/answers/757986/how-to-drilldown-from-panel-having-image-to-other.html

0 Karma
1 Solution

niketn
Legend

@pgadhari try something like the following run anywhere example. I have kept this simple for explanation so you can improve the JS to have a loop for setting and un-setting tokens.

The Simple XML Dashboard has images ( <img> ) inside <html> <panel>. The jQuery selector is used to identify the image clicked in Simple XML JS Extension and using SplunkJS stack it is used set/unset the required token/s.

alt text

Following is the Simple XML Dashboard code

<dashboard script="image_click_handler.js">
  <label>Panel with image for drilldown</label>
  <init>
    <set token="tokImgSrc">http://pngimg.com/uploads/server/server_PNG46.png</set>
    <set token="tokImgDtlSrc">https://www.groundreport.com/wp-content/uploads/2017/02/server-rack-colocation1.png</set>
  </init>
  <row>
    <panel id="html_panel1">
      <title>Panel 1</title>
      <html>
        <div style="display: flex;justify-content: center;">
          <div>
            <title>Panel 1</title>
          </div>
          <div>
            <img id="html_img1" class="click-image" style="height: 150px;cursor:pointer;" src="$tokImgSrc$"/>
          </div>
        </div>
      </html>
    </panel>
    <panel id="html_panel2">
      <title>Panel 2</title>
      <html>
        <div style="display: flex;justify-content: center;">
          <div>
            <title>Panel 2</title>
          </div>
          <div>
            <img id="html_img2" class="click-image" style="height: 150px;cursor:pointer;" src="$tokImgSrc$"/>
          </div>
        </div>
      </html>
    </panel>
    <panel id="html_panel3">
      <title>Panel 3</title>
      <html>
        <div style="display: flex;justify-content: center;">
          <div>
            <title>Panel 3</title>
          </div>
          <div>
            <img id="html_img3" class="click-image" style="height: 150px;cursor:pointer;" src="$tokImgSrc$"/>
          </div>
        </div>
      </html>
    </panel>
    <panel id="html_panel4">
      <title>Panel 4</title>
      <html>
        <div style="display: flex;justify-content: center;">
          <div>
            <title>Panel 4</title>
          </div>
          <div>
            <img id="html_img4" class="click-image" style="height: 150px;cursor:pointer;" src="$tokImgSrc$"/>
          </div>
        </div>
      </html>
    </panel>
    <panel id="html_panel5">
      <title>Panel 5</title>
      <html>
        <div style="display: flex;justify-content: center;">
          <div>
            <title>Panel 5</title>
          </div>
          <div>
            <img id="html_img5" class="click-image" style="height: 150px;cursor:pointer;" src="$tokImgSrc$"/>
          </div>
        </div>
      </html>
    </panel>
  </row>
  <row>
    <panel>
      <html>
        <div style="float:right">
          <a target="_blank" href="http://pngimg.com/download/25954">This Photo</a> by Unknown Author is licensed under <a target="_blank" href="https://creativecommons.org/licenses/by-nc/3.0/">CC BY-NC</a>
        </div>
      </html>
    </panel>
  </row>
  <row depends="$tokHtmlDtlImg1$">
    <panel>
      <title>Panel 1 Detail</title>
      <html>
        <div style="display:flex; justify-content:center;">
          <img style="width: 100%; height:300px" src="$tokImgDtlSrc$"/>
        </div>
      </html>
      <html>
        <div style="float:right;">
          <a target="_blank" href="https://www.groundreport.com/selecting-right-colocation-provider-points-consider">This Photo</a> by Unknown Author is licensed under <a target="_blank" href="https://creativecommons.org/licenses/by-nc/3.0/">CC BY-NC</a>
        </div>
      </html>
    </panel>
  </row>
  <row depends="$tokHtmlDtlImg2$">
    <panel>
      <title>Panel 2 Detail</title>
      <html>
        <div style="display:flex; justify-content:center;">
          <img style="width: 100%; height:300px" src="$tokImgDtlSrc$"/>
        </div>
      </html>
      <html>
        <div style="float:right;">
          <a target="_blank" href="https://www.groundreport.com/selecting-right-colocation-provider-points-consider">This Photo</a> by Unknown Author is licensed under <a target="_blank" href="https://creativecommons.org/licenses/by-nc/3.0/">CC BY-NC</a>
        </div>
      </html>
    </panel>
  </row>
  <row depends="$tokHtmlDtlImg3$">
    <panel>
      <title>Panel 3 Detail</title>
      <html>
        <div style="display:flex; justify-content:center;">
          <img style="width: 100%; height:300px" src="$tokImgDtlSrc$"/>
        </div>
      </html>
      <html>
        <div style="float:right;">
          <a target="_blank" href="https://www.groundreport.com/selecting-right-colocation-provider-points-consider">This Photo</a> by Unknown Author is licensed under <a target="_blank" href="https://creativecommons.org/licenses/by-nc/3.0/">CC BY-NC</a>
        </div>
      </html>
    </panel>
  </row>
  <row depends="$tokHtmlDtlImg4$">
    <panel>
      <title>Panel 4 Detail</title>
      <html>
        <div style="display:flex; justify-content:center;">
          <img style="width: 100%; height:300px" src="$tokImgDtlSrc$"/>
        </div>
      </html>
      <html>
        <div style="float:right;">
          <a target="_blank" href="https://www.groundreport.com/selecting-right-colocation-provider-points-consider">This Photo</a> by Unknown Author is licensed under <a target="_blank" href="https://creativecommons.org/licenses/by-nc/3.0/">CC BY-NC</a>
        </div>
      </html>
    </panel>
  </row>
  <row depends="$tokHtmlDtlImg5$">
    <panel>
      <title>Panel 5 Detail</title>
      <html>
        <div style="display:flex; justify-content:center;">
          <img style="width: 100%; height:300px" src="$tokImgDtlSrc$"/>
        </div>
      </html>
      <html>
        <div style="float:right;">
          <a target="_blank" href="https://www.groundreport.com/selecting-right-colocation-provider-points-consider">This Photo</a> by Unknown Author is licensed under <a target="_blank" href="https://creativecommons.org/licenses/by-nc/3.0/">CC BY-NC</a>
        </div>
      </html>
    </panel>
  </row>
</dashboard>

Following is the JS file image_click_handler.js required to enable image click handling to set/unset tokens:

require(["jquery",
    "splunkjs/mvc",
    "splunkjs/mvc/simplexml/ready!"
], function ($, mvc) {
    console.log("Inside Image Click Handler");
    var submittedTokenModel = mvc.Components.get("submitted");
    var defaultTokenModel = mvc.Components.get("default");
    $(document).on('click', 'div[id^="html_panel"] .click-image', function () {
        console.log("HTML Panel Image clicked");
        var strClickedImgID= $(this).attr("id");
        console.log("strClickedImgID:",strClickedImgID);
        switch (strClickedImgID) {
          case "html_img1":
            defaultTokenModel.set("tokHtmlDtlImg1", "true");
            submittedTokenModel.set("tokHtmlDtlImg1", "true");
            defaultTokenModel.unset("tokHtmlDtlImg2");
            submittedTokenModel.unset("tokHtmlDtlImg2");
            defaultTokenModel.unset("tokHtmlDtlImg3");
            submittedTokenModel.unset("tokHtmlDtlImg3");
            defaultTokenModel.unset("tokHtmlDtlImg4");
            submittedTokenModel.unset("tokHtmlDtlImg4");
            defaultTokenModel.unset("tokHtmlDtlImg5");
            submittedTokenModel.unset("tokHtmlDtlImg5");
            break;
          case "html_img2":
            defaultTokenModel.unset("tokHtmlDtlImg1");
            submittedTokenModel.unset("tokHtmlDtlImg1");
            defaultTokenModel.set("tokHtmlDtlImg2", "true");
            submittedTokenModel.set("tokHtmlDtlImg2", "true");
            defaultTokenModel.unset("tokHtmlDtlImg3");
            submittedTokenModel.unset("tokHtmlDtlImg3");
            defaultTokenModel.unset("tokHtmlDtlImg4");
            submittedTokenModel.unset("tokHtmlDtlImg4");
            defaultTokenModel.unset("tokHtmlDtlImg5");
            submittedTokenModel.unset("tokHtmlDtlImg5");
            break;
          case "html_img3":
            defaultTokenModel.unset("tokHtmlDtlImg1");
            submittedTokenModel.unset("tokHtmlDtlImg1");
            defaultTokenModel.unset("tokHtmlDtlImg2");
            submittedTokenModel.unset("tokHtmlDtlImg2");
            defaultTokenModel.set("tokHtmlDtlImg3", "true");
            submittedTokenModel.set("tokHtmlDtlImg3", "true");
            defaultTokenModel.unset("tokHtmlDtlImg4");
            submittedTokenModel.unset("tokHtmlDtlImg4");
            defaultTokenModel.unset("tokHtmlDtlImg5");
            submittedTokenModel.unset("tokHtmlDtlImg5");
            break;
          case "html_img4":
            defaultTokenModel.unset("tokHtmlDtlImg1");
            submittedTokenModel.unset("tokHtmlDtlImg1");
            defaultTokenModel.unset("tokHtmlDtlImg2");
            submittedTokenModel.unset("tokHtmlDtlImg2");
            defaultTokenModel.unset("tokHtmlDtlImg3");
            submittedTokenModel.unset("tokHtmlDtlImg3");
            defaultTokenModel.set("tokHtmlDtlImg4", "true");
            submittedTokenModel.set("tokHtmlDtlImg4", "true");
            defaultTokenModel.unset("tokHtmlDtlImg5");
            submittedTokenModel.unset("tokHtmlDtlImg5");
            break;
          case "html_img5":
            defaultTokenModel.unset("tokHtmlDtlImg1");
            submittedTokenModel.unset("tokHtmlDtlImg1");
            defaultTokenModel.unset("tokHtmlDtlImg2");
            submittedTokenModel.unset("tokHtmlDtlImg2");
            defaultTokenModel.unset("tokHtmlDtlImg3");
            submittedTokenModel.unset("tokHtmlDtlImg3");
            defaultTokenModel.unset("tokHtmlDtlImg4");
            submittedTokenModel.unset("tokHtmlDtlImg4");
            defaultTokenModel.set("tokHtmlDtlImg5", "true");
            submittedTokenModel.set("tokHtmlDtlImg5", "true");
            break;
          default:
            defaultTokenModel.unset("tokHtmlDtlImg1");
            submittedTokenModel.unset("tokHtmlDtlImg1");
            defaultTokenModel.unset("tokHtmlDtlImg2");
            submittedTokenModel.unset("tokHtmlDtlImg2");
            defaultTokenModel.unset("tokHtmlDtlImg3");
            submittedTokenModel.unset("tokHtmlDtlImg3");
            defaultTokenModel.unset("tokHtmlDtlImg4");
            submittedTokenModel.unset("tokHtmlDtlImg4");
            defaultTokenModel.unset("tokHtmlDtlImg5");
            submittedTokenModel.unset("tokHtmlDtlImg5");
        }
    });
});
____________________________________________
| makeresults | eval message= "Happy Splunking!!!"

View solution in original post

0 Karma

niketn
Legend

@pgadhari try something like the following run anywhere example. I have kept this simple for explanation so you can improve the JS to have a loop for setting and un-setting tokens.

The Simple XML Dashboard has images ( <img> ) inside <html> <panel>. The jQuery selector is used to identify the image clicked in Simple XML JS Extension and using SplunkJS stack it is used set/unset the required token/s.

alt text

Following is the Simple XML Dashboard code

<dashboard script="image_click_handler.js">
  <label>Panel with image for drilldown</label>
  <init>
    <set token="tokImgSrc">http://pngimg.com/uploads/server/server_PNG46.png</set>
    <set token="tokImgDtlSrc">https://www.groundreport.com/wp-content/uploads/2017/02/server-rack-colocation1.png</set>
  </init>
  <row>
    <panel id="html_panel1">
      <title>Panel 1</title>
      <html>
        <div style="display: flex;justify-content: center;">
          <div>
            <title>Panel 1</title>
          </div>
          <div>
            <img id="html_img1" class="click-image" style="height: 150px;cursor:pointer;" src="$tokImgSrc$"/>
          </div>
        </div>
      </html>
    </panel>
    <panel id="html_panel2">
      <title>Panel 2</title>
      <html>
        <div style="display: flex;justify-content: center;">
          <div>
            <title>Panel 2</title>
          </div>
          <div>
            <img id="html_img2" class="click-image" style="height: 150px;cursor:pointer;" src="$tokImgSrc$"/>
          </div>
        </div>
      </html>
    </panel>
    <panel id="html_panel3">
      <title>Panel 3</title>
      <html>
        <div style="display: flex;justify-content: center;">
          <div>
            <title>Panel 3</title>
          </div>
          <div>
            <img id="html_img3" class="click-image" style="height: 150px;cursor:pointer;" src="$tokImgSrc$"/>
          </div>
        </div>
      </html>
    </panel>
    <panel id="html_panel4">
      <title>Panel 4</title>
      <html>
        <div style="display: flex;justify-content: center;">
          <div>
            <title>Panel 4</title>
          </div>
          <div>
            <img id="html_img4" class="click-image" style="height: 150px;cursor:pointer;" src="$tokImgSrc$"/>
          </div>
        </div>
      </html>
    </panel>
    <panel id="html_panel5">
      <title>Panel 5</title>
      <html>
        <div style="display: flex;justify-content: center;">
          <div>
            <title>Panel 5</title>
          </div>
          <div>
            <img id="html_img5" class="click-image" style="height: 150px;cursor:pointer;" src="$tokImgSrc$"/>
          </div>
        </div>
      </html>
    </panel>
  </row>
  <row>
    <panel>
      <html>
        <div style="float:right">
          <a target="_blank" href="http://pngimg.com/download/25954">This Photo</a> by Unknown Author is licensed under <a target="_blank" href="https://creativecommons.org/licenses/by-nc/3.0/">CC BY-NC</a>
        </div>
      </html>
    </panel>
  </row>
  <row depends="$tokHtmlDtlImg1$">
    <panel>
      <title>Panel 1 Detail</title>
      <html>
        <div style="display:flex; justify-content:center;">
          <img style="width: 100%; height:300px" src="$tokImgDtlSrc$"/>
        </div>
      </html>
      <html>
        <div style="float:right;">
          <a target="_blank" href="https://www.groundreport.com/selecting-right-colocation-provider-points-consider">This Photo</a> by Unknown Author is licensed under <a target="_blank" href="https://creativecommons.org/licenses/by-nc/3.0/">CC BY-NC</a>
        </div>
      </html>
    </panel>
  </row>
  <row depends="$tokHtmlDtlImg2$">
    <panel>
      <title>Panel 2 Detail</title>
      <html>
        <div style="display:flex; justify-content:center;">
          <img style="width: 100%; height:300px" src="$tokImgDtlSrc$"/>
        </div>
      </html>
      <html>
        <div style="float:right;">
          <a target="_blank" href="https://www.groundreport.com/selecting-right-colocation-provider-points-consider">This Photo</a> by Unknown Author is licensed under <a target="_blank" href="https://creativecommons.org/licenses/by-nc/3.0/">CC BY-NC</a>
        </div>
      </html>
    </panel>
  </row>
  <row depends="$tokHtmlDtlImg3$">
    <panel>
      <title>Panel 3 Detail</title>
      <html>
        <div style="display:flex; justify-content:center;">
          <img style="width: 100%; height:300px" src="$tokImgDtlSrc$"/>
        </div>
      </html>
      <html>
        <div style="float:right;">
          <a target="_blank" href="https://www.groundreport.com/selecting-right-colocation-provider-points-consider">This Photo</a> by Unknown Author is licensed under <a target="_blank" href="https://creativecommons.org/licenses/by-nc/3.0/">CC BY-NC</a>
        </div>
      </html>
    </panel>
  </row>
  <row depends="$tokHtmlDtlImg4$">
    <panel>
      <title>Panel 4 Detail</title>
      <html>
        <div style="display:flex; justify-content:center;">
          <img style="width: 100%; height:300px" src="$tokImgDtlSrc$"/>
        </div>
      </html>
      <html>
        <div style="float:right;">
          <a target="_blank" href="https://www.groundreport.com/selecting-right-colocation-provider-points-consider">This Photo</a> by Unknown Author is licensed under <a target="_blank" href="https://creativecommons.org/licenses/by-nc/3.0/">CC BY-NC</a>
        </div>
      </html>
    </panel>
  </row>
  <row depends="$tokHtmlDtlImg5$">
    <panel>
      <title>Panel 5 Detail</title>
      <html>
        <div style="display:flex; justify-content:center;">
          <img style="width: 100%; height:300px" src="$tokImgDtlSrc$"/>
        </div>
      </html>
      <html>
        <div style="float:right;">
          <a target="_blank" href="https://www.groundreport.com/selecting-right-colocation-provider-points-consider">This Photo</a> by Unknown Author is licensed under <a target="_blank" href="https://creativecommons.org/licenses/by-nc/3.0/">CC BY-NC</a>
        </div>
      </html>
    </panel>
  </row>
</dashboard>

Following is the JS file image_click_handler.js required to enable image click handling to set/unset tokens:

require(["jquery",
    "splunkjs/mvc",
    "splunkjs/mvc/simplexml/ready!"
], function ($, mvc) {
    console.log("Inside Image Click Handler");
    var submittedTokenModel = mvc.Components.get("submitted");
    var defaultTokenModel = mvc.Components.get("default");
    $(document).on('click', 'div[id^="html_panel"] .click-image', function () {
        console.log("HTML Panel Image clicked");
        var strClickedImgID= $(this).attr("id");
        console.log("strClickedImgID:",strClickedImgID);
        switch (strClickedImgID) {
          case "html_img1":
            defaultTokenModel.set("tokHtmlDtlImg1", "true");
            submittedTokenModel.set("tokHtmlDtlImg1", "true");
            defaultTokenModel.unset("tokHtmlDtlImg2");
            submittedTokenModel.unset("tokHtmlDtlImg2");
            defaultTokenModel.unset("tokHtmlDtlImg3");
            submittedTokenModel.unset("tokHtmlDtlImg3");
            defaultTokenModel.unset("tokHtmlDtlImg4");
            submittedTokenModel.unset("tokHtmlDtlImg4");
            defaultTokenModel.unset("tokHtmlDtlImg5");
            submittedTokenModel.unset("tokHtmlDtlImg5");
            break;
          case "html_img2":
            defaultTokenModel.unset("tokHtmlDtlImg1");
            submittedTokenModel.unset("tokHtmlDtlImg1");
            defaultTokenModel.set("tokHtmlDtlImg2", "true");
            submittedTokenModel.set("tokHtmlDtlImg2", "true");
            defaultTokenModel.unset("tokHtmlDtlImg3");
            submittedTokenModel.unset("tokHtmlDtlImg3");
            defaultTokenModel.unset("tokHtmlDtlImg4");
            submittedTokenModel.unset("tokHtmlDtlImg4");
            defaultTokenModel.unset("tokHtmlDtlImg5");
            submittedTokenModel.unset("tokHtmlDtlImg5");
            break;
          case "html_img3":
            defaultTokenModel.unset("tokHtmlDtlImg1");
            submittedTokenModel.unset("tokHtmlDtlImg1");
            defaultTokenModel.unset("tokHtmlDtlImg2");
            submittedTokenModel.unset("tokHtmlDtlImg2");
            defaultTokenModel.set("tokHtmlDtlImg3", "true");
            submittedTokenModel.set("tokHtmlDtlImg3", "true");
            defaultTokenModel.unset("tokHtmlDtlImg4");
            submittedTokenModel.unset("tokHtmlDtlImg4");
            defaultTokenModel.unset("tokHtmlDtlImg5");
            submittedTokenModel.unset("tokHtmlDtlImg5");
            break;
          case "html_img4":
            defaultTokenModel.unset("tokHtmlDtlImg1");
            submittedTokenModel.unset("tokHtmlDtlImg1");
            defaultTokenModel.unset("tokHtmlDtlImg2");
            submittedTokenModel.unset("tokHtmlDtlImg2");
            defaultTokenModel.unset("tokHtmlDtlImg3");
            submittedTokenModel.unset("tokHtmlDtlImg3");
            defaultTokenModel.set("tokHtmlDtlImg4", "true");
            submittedTokenModel.set("tokHtmlDtlImg4", "true");
            defaultTokenModel.unset("tokHtmlDtlImg5");
            submittedTokenModel.unset("tokHtmlDtlImg5");
            break;
          case "html_img5":
            defaultTokenModel.unset("tokHtmlDtlImg1");
            submittedTokenModel.unset("tokHtmlDtlImg1");
            defaultTokenModel.unset("tokHtmlDtlImg2");
            submittedTokenModel.unset("tokHtmlDtlImg2");
            defaultTokenModel.unset("tokHtmlDtlImg3");
            submittedTokenModel.unset("tokHtmlDtlImg3");
            defaultTokenModel.unset("tokHtmlDtlImg4");
            submittedTokenModel.unset("tokHtmlDtlImg4");
            defaultTokenModel.set("tokHtmlDtlImg5", "true");
            submittedTokenModel.set("tokHtmlDtlImg5", "true");
            break;
          default:
            defaultTokenModel.unset("tokHtmlDtlImg1");
            submittedTokenModel.unset("tokHtmlDtlImg1");
            defaultTokenModel.unset("tokHtmlDtlImg2");
            submittedTokenModel.unset("tokHtmlDtlImg2");
            defaultTokenModel.unset("tokHtmlDtlImg3");
            submittedTokenModel.unset("tokHtmlDtlImg3");
            defaultTokenModel.unset("tokHtmlDtlImg4");
            submittedTokenModel.unset("tokHtmlDtlImg4");
            defaultTokenModel.unset("tokHtmlDtlImg5");
            submittedTokenModel.unset("tokHtmlDtlImg5");
        }
    });
});
____________________________________________
| makeresults | eval message= "Happy Splunking!!!"
0 Karma

pgadhari
Builder

Thanks. I will try this out and revert back.

0 Karma

niketn
Legend

@pgadhari were you able to try the above solution?

____________________________________________
| makeresults | eval message= "Happy Splunking!!!"
0 Karma

pgadhari
Builder

@niketnilay - No, I did not tried it as this project was on hold for sometime. Next week I will try it as I have to kick off this again and it has to be started. Thanks for your support and answer. I will get back in case of any issues. Thanks.

0 Karma

niketn
Legend

@pgadhari also wanted you to check out one of other answers with a Table Tile based approach which is purely Simple XML with CSS override and does not require JS Extension if that is your requirement: https://answers.splunk.com/answers/529004/is-there-a-way-to-display-more-than-20-charts-at-a.html#an...

____________________________________________
| makeresults | eval message= "Happy Splunking!!!"

pgadhari
Builder

@niketnilay - Sure I will check that out.

0 Karma

niketn
Legend

@pgadhari please upvote the other answer if worked for you. Also accept this answer if your issue is resolved! 🙂

____________________________________________
| makeresults | eval message= "Happy Splunking!!!"
0 Karma

pgadhari
Builder

@niketnilay - sure I will accept the answer. Actually, one more thing, I am working on creating new landing page for our splunk environment. Hence, I will need some help on JS and CSS stuff, would request you to extend your help in case i face any issues in that. I will open new question on that shortly.

thanks again for all your support.

0 Karma

niketn
Legend

@pgadhari seems like what you have done with html dashboard can also be done with Simple XML. Any specific reason for choosing html dashboard?

If you keep panels to Simple XML you can also implment tabs in Splunk Dashboard using Simple XML JS/CSS extension.

____________________________________________
| makeresults | eval message= "Happy Splunking!!!"
0 Karma

pgadhari
Builder

@niketnilay - I was not sure of whether it can be done with simple XML. I got the answer that I need to convert the dashboard to HTML and then use the show & hide function to show the panels based on the clicks. Can you show me how it can be done with simple XML ?

Please go through my previous question:

https://answers.splunk.com/answers/757986/how-to-drilldown-from-panel-having-image-to-other.html

0 Karma
Get Updates on the Splunk Community!

Adoption of RUM and APM at Splunk

    Unleash the power of Splunk Observability   Watch Now In this can't miss Tech Talk! The Splunk Growth ...

March Community Office Hours Security Series Uncovered!

Hello Splunk Community! In March, Splunk Community Office Hours spotlighted our fabulous Splunk Threat ...

Stay Connected: Your Guide to April Tech Talks, Office Hours, and Webinars!

Take a look below to explore our upcoming Community Office Hours, Tech Talks, and Webinars in April. This post ...