Pushing the Limits of Tableau Server

Practical Lessons from a Zen Master

This is me.

This title is

not interesting enough

Tableau Software Hates Him*!

This One Weird Trick Will Change How You Build Dashboards.

*Actually they don't hate me.

But before that...

Some background

Tableau Javascript API

Embedding & Portal Integration

BOOOOORING!

*Real* Tableau JavaScript API Examples

Add "Paging" support to Server

By Allan Walker, Jeffrey Shaffer

    var viz, one, workbooka, activeSheet, Worksheet, worksheet;
    $(function() {
        var onePh = document.getElementById("tableauViz1");
        var oneUrl = "https://public.tableau.com/views/RoslinginTableau_3/RoslingGapminder?:showVizHome=no&:display_spinner=no&:jsdebug=n&:embed=y&:display_overlay=no&:display_static_image=no&:animate_transition=yes";
        var oneOptions = {
            width: "100%",
            height: "100vh",
            hideTabs: false,
            onFirstInteractive: function() {
                workbooka = viz1.getWorkbook();
                window.setTimeout("animate()", "1000");
            }
        };
        viz1 = new tableauSoftware.Viz(onePh, oneUrl, oneOptions);
        i = 1;
    });

    function animate() {
        if (i <= 62) {
            window.setTimeout("animate()", "2000");
            animate1(i);
            i++;
        }
    }

    function animate1(a) {
        workbooka.changeParameterValueAsync("ANIMATE", [a]);
    }

Better Tables in Views

(defn get-data-and-show-modal!
  [f]
  (-> (:vizobj @viz)
      (.getWorkbook)
      (.getActiveSheet)
      (f (clj->js @viz))
      (.then (fn [data]
               (swap! viz assoc :columns (.getColumns data) :data (.getData data))
               (reagent-modals/modal! [modal] {:size :lg}) ))))

(defn underlying-button []
  [:div.btn.btn-primary
   {:disabled (not (:ready @viz))
    :on-click (fn [] (get-data-and-show-modal! #(.getUnderlyingDataAsync %1 %2)))}
   "Show underlying data"])

(defn summary-button []
  [:div.btn.btn-primary
   {:disabled (not (:ready @viz))
    :on-click (fn [] (get-data-and-show-modal! #(.getSummaryDataAsync %1 %2)))}
   "Show summary data"])

Custom Chart Types

BUT THERE ARE TWO ISSUES

1.

You need to use an external portal

2.

Solution?

The One Weird Trick

You won't believe what's next!

I WILL SHOW IT

Javascript without Embedding

A Simple Example

Text

No need for external portal

Reusable "Plugins"

HOW?

var TableauLib = (function () {
    function TableauLib() {
    }
    TableauLib.prototype.getTableau = function () {
        if (!parent || !parent.parent) {
            return null;
        }
        var grandParent = parent.parent;
        return grandParent.tableau;
    };
    TableauLib.prototype.getCurrentViz = function () {
        var tableau = this.getTableau();
        if (!tableau) {
            return null;
        }
        return tableau.VizManager.getVizs()[0];
    };

//[...]

    return TableauLib;
}());

And it's reusable.

And now some REAL* use cases

* Not real, actually

BOSS MAN

RECORD LABEL

Auto refresh

"This is awesome. I’ve deployed it and it’s screaming. Great find!"

Reusable and customizable

Configuration

Parameter Description
autoRefresh_seconds The number of seconds to count down from
autoRefresh_radius The radius of the arc in pixels
autoRefresh_fontSize, autoRefresh_fontWeight, ​autoRefresh_fontColor,  The font style
autoRefresh_fillStyle The fill color
autoRefresh_strokeStyle The color of the stroke

End-to-End Security

Use Case

Client side decryption

Database and Tableau Server do not "see" the decrypted data

D3.JS

+

TABLEAU

But Why?

"Can I get this icon in corn flower blue?"

D3 Brush Filters

By Chris DeMartini

http://www.datablick.com/blog/2017/3/2/building-towards-d3js-plugins-for-tableau

Radar Chart

Collaboration

Write-back, comments, annotations

Data-point annotation on web

TabChat 2.0

And the grand finale 

with our guest star:

Tabular view & Excel Export

and this was just the beginning.

All sources & blog post on DataBoss

http://databoss.starschema.net/