Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2017 Tableau
Copyright (c) 2022 Tableau

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
20 changes: 7 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ The Extensions API lets you do more without leaving Tableau. Build Tableau exten
## Setup and Running Samples

### Prerequisites
* You must have Node.js and npm installed. You can get these from [http://nodejs.org](http://nodejs.org).
* You must have Node.js and npm installed. You can get these from [https://nodejs.org](https://nodejs.org).

### Install Extensions API SDK Components and Start Server

Expand All @@ -35,15 +35,14 @@ The Extensions API lets you do more without leaving Tableau. Build Tableau exten

### Typescript Development
Samples written in Typescript are located in the `Samples-Typescript` folder.
If you want to use TypeScript to write your extensions, you can run a script that starts up the HTTP server and actively listens for changes to the `.ts` files located in the `Sample-Typescript` folder. You can then add your extension to the folder and use the script to transpile your extension to JavaScript.
If you want to use TypeScript to write your extensions, you can run a script that starts up the HTTP server and actively listens for changes to the `.ts` files located in the `Samples-Typescript` folder. You can then add your extension to the folder and use the script to transpile your extension to JavaScript.

* To start the the HTTP server and listen for changes to the `.ts` files.

**npm run dev**

For more information, see [Use TypeScript with the Extensions API](https://tableau.github.io/extensions-api/docs/trex_typescript.html).


### Sandboxed Extension Development Environment

Tableau is introducing development support for Sandboxed Extensions with Tableau 2019.3. Sandboxed Extensions run in a virtual sandbox and ensure the extension can’t make network calls outside of the hosting Tableau Server. The Extensions API SDK provides a local development environment that replicates the Tableau Hosting Cloud Service for Sandboxed Extensions. You can test your Sandboxed extensions locally with the same sandbox policies.
Expand All @@ -56,22 +55,17 @@ Tableau is introducing development support for Sandboxed Extensions with Tableau

For more information, see [Create and Test Sandboxed Extensions](https://tableau.github.io/extensions-api/docs/trex_sandbox_test.html).

## Contributions
Contributions and improvements by the community are welcomed!
See the LICENSE file for current open-source licensing and use information.

## Submissions
We would love submissions to either the Docs or Sample code! To contribute, first sign our CLA that can be found [here](https://tableau.github.io/contributing.html). To submit a contribution, please fork the repository then submit a pull request to the `submissions` branch.
Before we can accept pull requests from contributors, we require a signed [Contributor License Agreement (CLA)](https://tableau.github.io/contributing.html). To submit a contribution, please fork the repository then submit a pull request to the `main` branch.

## Code Style
Our sample code follows the [Semi-Standard Style](https://github.com/Flet/semistandard) for JavaScript samples linting and [tslint](https://palantir.github.io/tslint/) for TypeScript. If you add your own extension code to the Samples or Samples-Typescript directories, you can run `npm run lint` to validate the style of your code. Please run this command before submitting any pull requests for Sample code.

## Contributions
Code contributions and improvements by the community are welcomed!
See the LICENSE file for current open-source licensing and use information.

Before we can accept pull requests from contributors, we require a signed [Contributor License Agreement (CLA)](http://tableau.github.io/contributing.html).

## Documentation
[Visit the project website and read the documentation here.](https://tableau.github.io/extensions-api/)


## Issues
Use [Issues](https://github.com/tableau/ProjectFrelard/issues) to log any problems or bugs you encounter in the docs or sample code.
Use [Issues](https://github.com/tableau/extensions-api/issues) to log any problems you encounter in the docs or sample code, or to discuss any proposed changes or additions.
2 changes: 1 addition & 1 deletion _includes/docs_menu.html
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@
<a href="{{ site.baseurl }}/docs/index.html" target="_blank">API Reference</a>
</li>
<li>
<a href="{{ site.baseurl }}/docs/trex_tableau_viz_ref.html" target="_blank">Tableau Viz Reference</a>
<a href="{{ site.baseurl }}/docs/trex_tableau_viz_ref.html">Tableau Viz Reference</a>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My mistake. The VizAPI isn't a separate doc set and so it shouldn't have the target="_blank"

</li>
<li>
<a href="{{ site.baseurl }}/docs/trex_release-notes.html">Release Notes</a>
Expand Down
2 changes: 1 addition & 1 deletion _includes/header.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<li><a href="{{ site.baseurl }}/docs/trex_release-notes.html">Release Notes</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li class="tableauIcon"><a target="_blank" href="http://tableau.com"><img src="{{ site.baseurl }}/assets/logo.png" alt="Tableau Developers" class="logo" /></a></li>
<li class="tableauIcon"><a target="_blank" href="https://www.tableau.com/developer"><img src="{{ site.baseurl }}/assets/logo.png" alt="Tableau Developers" class="logo" /></a></li>
<li><a target="_blank" href="https://github.com/tableau/extensions-api"><span class="icon icon--github" title="Extensions API on GitHub" alt="Extensions API on GitHub">{% include icon-github.svg %}</span></a></li>
</ul>
</div><!--/.nav-collapse -->
Expand Down
4 changes: 2 additions & 2 deletions _layouts/docs.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
<div class="content .col-xs-12 .col-sm-8 .col-md-9">
<h1>{{ page.title }}</h1>
<div class="edit-container">
<a href="https://github.com/tableau/projectfrelard/edit/master/{{ page.path }}" class="edit-links"><span class="glyphicon glyphicon-pencil"></span> Edit this page</a>
<a href="https://github.com/tableau/extensions-api/edit/main/{{ page.path }}" class="edit-links"><span class="glyphicon glyphicon-pencil"></span> Edit this page</a>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bcantoni Good catch! Project Frelard was the code name and the name of the repo when we were first launching.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed - luckily GitHub does the right thing and handles with a redirect both the repo name and default branch name changes.

&nbsp;
<a href="https://github.com/tableau/projectfrelard/issues" class="edit-links"><span class="glyphicon glyphicon-flag"></span> Submit an issue</a>
<a href="https://github.com/tableau/extensions-api/issues" class="edit-links"><span class="glyphicon glyphicon-flag"></span> Submit an issue</a>
</div>
<br />

Expand Down
4 changes: 2 additions & 2 deletions _layouts/guide.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
<div class="content .col-xs-12 .col-sm-8 .col-md-9">
<h1>{{ page.title }}</h1>
<div class="edit-container">
<a href="https://github.com/tableau/projectfrelard/edit/master/{{ page.path }}" class="edit-links"><span class="glyphicon glyphicon-pencil"></span> Edit this page</a>
<a href="https://github.com/tableau/extensions-api/edit/master/{{ page.path }}" class="edit-links"><span class="glyphicon glyphicon-pencil"></span> Edit this page</a>
&nbsp;
<a href="https://github.com/tableau/projectfrelard/issues" class="edit-links"><span class="glyphicon glyphicon-flag"></span> Submit an issue</a>
<a href="https://github.com/tableau/extensions-api/issues" class="edit-links"><span class="glyphicon glyphicon-flag"></span> Submit an issue</a>
</div>
<br />

Expand Down
Binary file modified assets/frelard_objects_extension.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 6 additions & 28 deletions docs/Interaction_Guidelines/ux_build_test.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,8 @@ layout: guide

This section serves as a broad overview of the developer experience and considerations of making extensions.

&nbsp;

![lifecycle](./imgs/1-lifecycle.png)

&nbsp;

## Build
The first thing to do is start running sample extension code from the Extensions API Documentation. **Make sure that your sample code works** and your environment is set up properly before jumping into building a new extension.

Expand All @@ -23,42 +19,24 @@ Once you're ready to go, you can start building and customizing your extension.

* [Community Forums](https://community.tableau.com/community/developers/extensions-api/overview)<br>Participate in a community of developers that are passionate about creating extensions.

* [Extension Gallery (beta)](https://extensiongallery.tableau.com/)<br>Explore and use some of the extensions our partners have created.
* [Tableau Exchange](https://exchange.tableau.com/)<br>Explore and use some of the extensions our partners have created.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for catching all these gallery references. I missed them completely when I updated references earlier.


* [Developer Preview](https://prerelease.tableau.com/extensions-api)<br>Participate in the Developer Preview for our Extensions API. Be invited to bi-weekly sprint demos with Tableau's development team and have the opportunity to give ongoing feedback.

&nbsp;

## Test
Ensure that your extension works properly for different test cases. Try it on your own dashboards, test it with others, and uncover possible edge cases.

Consider that dashboard extensions can be both **configured** and **viewed** in Tableau. These terms refer to two usage modes we recommend for extensions. To read about these modes and their audiences, learn more at **[Extension Components and Modes]({{ site.baseurl }}/docs/Interaction_Guidelines/ux_components_modes.html)**.


&nbsp;

## Share
After you've completed making your extension, you may want to share your extension for others to use. Here are some places you might think about sharing your extension.

### Tableau Exchange
Tableau has released the [Tableau Exchange](https://exchange.tableau.com/), a place to explore and download some extensions that our partners have created. If you would like to share your extension, learn more at [Sharing to the Tableau Exchange]({{site.baseurl}}/docs/ux_extension_gallery.html).

##### Extension Gallery
Tableau has released the [Extension Gallery](https://extensiongallery.tableau.com/), a place to explore and download some extensions that our partners have created. If you would like to share your extension to our gallery, learn more at [Sharing to the Extension Gallery]({{site.baseurl}}/docs/ux_extension_gallery.html).
### Community Forums
Tableau also has a [Community Forum](https://community.tableau.com/s/) for developers to discuss extensions and the Extensions API.

##### Community Forums
Tableau also has a [Community Forum](https://community.tableau.com/community/developers/extensions-api/overview) for developers to discuss extensions and the Extensions API.

----- &nbsp;
-----

While you might not choose to share your extension directly with Tableau, we encourage you to share your extension through other platforms of your choice! Use it internally at your company or for yourself, consider open source platforms, share over social media channels. How you go about sharing your extension with the world is entirely up to you.

&nbsp;

&nbsp;

---
<!--
### <div id="expand-box"><div id="expand-box-header">[<span style="float: right;">2 – Extension Components and Modes &#8594;</span>](2 - Extension Components and Modes.md)</div></div>

##### <div id="expand-box"><div id="expand-box-header">[<span style="float: left;">Interaction Guidelines</span>](Interaction Guidelines)</div></div>

-->
25 changes: 8 additions & 17 deletions docs/trex_api_about.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,23 @@ The [Extensions API Reference]({{site.baseurl}}\docs\index.html) namespaces are

The `extensions` namespace is the namespace for Tableau extensions. A dashboard extension is one type of extension. When a extension is registered as a dashboard extension, it has access to the `dashboardContent` namespace, and all of the objects and classes of the dashboard. The type of extension you have registered determines what namespaces will be available. Some namespaces, like the `settings`, `environment`, and `ui` are available to all extensions.

The `extensions` name space has one method `initializeAsync()` that is used to initialize the extension. When this method is called, it also triggers Tableau to configure the Extensions API. Like the Tableau JavaScript API, the Extensions API follows the [CommonJS Promises/A standard](http://wiki.commonjs.org/wiki/Promises/A) for asynchronous method calls.
The `extensions` namespace has one method `initializeAsync()` that is used to initialize the extension. When this method is called, it also triggers Tableau to configure the Extensions API. Like the Tableau JavaScript API, the Extensions API follows the [CommonJS Promises/A standard](http://wiki.commonjs.org/wiki/Promises/A) for asynchronous method calls.

![]({{site.baseurl}}/assets/tab_ext_class.png)

## Registering and accessing dashboard extensions

The dashboard extension is one type of extension in the Tableau extensions namespace (and it is accessed using `tableau.extensions`). To register the extension, you declare the type of extension in the manifest file (`.trex`). For more information about what goes in the file, see [Tableau Manifest File]({{site.baseurl}}\docs\index.html).
The dashboard extension is one type of extension in the Tableau extensions namespace (and it is accessed using `tableau.extensions`). To register the extension, you declare the type of extension in the manifest file (`.trex`). For more information about what goes in the file, see [Tableau Manifest File](./trex_manifest.md).
Copy link
Contributor

@d45 d45 Feb 2, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My mistake. The link when to the API reference page. The url should be {{site.baseurl}}\docs\trex_manifest.html

So the full link is:
[Tableau Manifest File]({{site.baseurl}}\docs\trex_manifest.html)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's cleaner and perhaps more standard to just point to the relative .md file like this. These will resolve correctly when published but also when doing a local jekyll build.


```xml
<dashboard-extension id="com.example.extensions.name" extension-version="0.1.0">
<dashboard-extension id="com.example.extensions.name" extension-version="0.1.0">
```
After the extension is initialized, it provides access to the objects in the dashboard, but also has access to the namespaces that are common to all extensions. For example, you can use the `tableau.extensions.environment` to query the environment the dashboard is running in, or `tableau.extensions.settings` to set or get key-value pairs associated with the extension. The `tableau.extensions.settings` can be saved with the workbook, so you can configure the dashboard and the extension in specific ways and then share that configuration with others.

To access the objects in the dashboard, you specify the namespace reserved for dashboard extensions `dashboardContent`, which then gives you access to the dashboard object. For example, the following code snippet gets the array of worksheets in the dashboard.

```python
const worksheets = tableau.extensions.dashboardContent.dashboard.worksheets ;
```javascript
const worksheets = tableau.extensions.dashboardContent.dashboard.worksheets;
```

The following diagram shows an outline of the namespace hierarchy that you traverse to get to worksheets.
Expand All @@ -49,16 +49,7 @@ For example, after you extract a worksheet object from the dashboard, you can us

The following code fragment shows an example of setting an event listener `addEventListener` on a worksheet.

```python

// Add an event listener for the selection changed event on this sheet.
unregisterEventHandlerFunction = worksheet.addEventListener('mark-selection-changed', myfunctionHandleSelectionEvent);
```javascript
// Add an event listener for the selection changed event on this sheet.
let unregisterEventHandlerFunction = worksheet.addEventListener('mark-selection-changed', myfunctionHandleSelectionEvent);
```








55 changes: 23 additions & 32 deletions docs/trex_configure.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ The first step is to add the `<context-menu>` option to the extension's manifest
<context-menu>
<configure-context-menu-item />
</context-menu>

```


Expand All @@ -36,14 +35,12 @@ This object maps a special ID or key (which must be `'configure'`) to a function
with adding a `<context-menu>` item to the manifest, adds a new **Configure...** context menu item to the zone of the extension inside a dashboard. When the user clicks the context menu item, the configuration function you specified is executed.


![]({{site.baseurl}}/assets/extension_configure_menu.png){:height="25%" width="25%"}
![]({{site.baseurl}}/assets/extension_configure_menu.png){:height="25%" width="25%"}


For example, you could use the UI namespace and have the configuration function call the `displayDialogAsync()` function to create a dialog box that can be used to change settings for the extension. The parent (or initial window) for your extension, might have the following JavaScript code. This example uses an initial payload string value, *defaultIntervalInMin*, to pass to the configuration dialog. The payload value is modified in the configuration dialog and is returned in the `closeDialog()` method. Alternatively, you could use a `Settings` object to store the key/value pairs that configure your extension.

```javascript


// Wrap everything in an anonymous function to avoid polluting the global namespace
(function () {
const defaultIntervalInMin = '5';
Expand All @@ -54,12 +51,9 @@ $(document).ready(function () {
// ...
tableau.extensions.initializeAsync({'configure': configure}).then(function() {
// ...
// ... code to set up event handlers for changes to configuration
// ... code to set up event handlers for changes to configuration
});
});
});



function configure() {
// ... code to configure the extension
Expand All @@ -82,39 +76,36 @@ $(document).ready(function () {
}

})();

```

In the JavaScript code for the popup dialog window, you would add your code for initializing the dialog and for setting and saving the configuration settings.

```javascript

$(document).ready(function () {
// The only difference between an extension in a dashboard and an extension
// running in a popup is that the popup extension must use the method
// initializeDialogAsync instead of initializeAsync for initialization.
// This has no affect on the development of the extension but is used internally.
tableau.extensions.initializeDialogAsync().then(function (openPayload) {
// The openPayload sent from the parent extension in this example is the
// default time interval for the refreshes. This could alternatively be stored
// in settings, but is used in this sample to demonstrate open and close payloads.
// code goes here
});
});

$(document).ready(function () {
// The only difference between an extension in a dashboard and an extension
// running in a popup is that the popup extension must use the method
// initializeDialogAsync instead of initializeAsync for initialization.
// This has no affect on the development of the extension but is used internally.
tableau.extensions.initializeDialogAsync().then(function (openPayload) {
// The openPayload sent from the parent extension in this example is the
// default time interval for the refreshes. This could alternatively be stored
// in settings, but is used in this sample to demonstrate open and close payloads.
// code goes here
});
});
```

In your code to close the popup window, you must pass a string value (or empty string `" "`) as the return payload, even if you are using the `Settings` object to pass your configuration parameters.

```javascript
function closeDialog() {
// Save the settings with tableau.extensions.settings.saveAsync()
// Or pass the new configuration setting in the close payload
tableau.extensions.ui.closeDialog('NewInterval');
console.log("Settings saved");
});
}

function closeDialog() {
// Save the settings with tableau.extensions.settings.saveAsync()
// Or pass the new configuration setting in the close payload
tableau.extensions.ui.closeDialog('NewInterval');
console.log("Settings saved");
});
}
```

To better understand how to use the context menu, and to see it in action, check out the [UINamespace](https://github.com/tableau/extensions-api/tree/master/Samples/UINamespace?=target="_blank") sample.
To better understand how to use the context menu, and to see it in action, check out the [UINamespace](https://github.com/tableau/extensions-api/tree/main/Samples/UINamespace?=target="_blank") sample.

Loading