diff --git a/LICENSE b/LICENSE index 42148a81..06d514c2 100644 --- a/LICENSE +++ b/LICENSE @@ -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 diff --git a/README.md b/README.md index 8970a7a8..67183d00 100644 --- a/README.md +++ b/README.md @@ -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 @@ -35,7 +35,7 @@ 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. @@ -43,7 +43,6 @@ If you want to use TypeScript to write your extensions, you can run a script tha 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. @@ -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. diff --git a/_includes/docs_menu.html b/_includes/docs_menu.html index bd1ba765..b18edcfe 100644 --- a/_includes/docs_menu.html +++ b/_includes/docs_menu.html @@ -91,7 +91,7 @@ API Reference
  • - Tableau Viz Reference + Tableau Viz Reference
  • Release Notes diff --git a/_includes/header.html b/_includes/header.html index 86f90e1a..7723de69 100644 --- a/_includes/header.html +++ b/_includes/header.html @@ -22,7 +22,7 @@
  • Release Notes
  • diff --git a/_layouts/docs.html b/_layouts/docs.html index 881bcecb..eea65e56 100644 --- a/_layouts/docs.html +++ b/_layouts/docs.html @@ -17,9 +17,9 @@

    {{ page.title }}

    - Edit this page + Edit this page   - Submit an issue + Submit an issue

    diff --git a/_layouts/guide.html b/_layouts/guide.html index 77dbffd6..d9a4eb3d 100644 --- a/_layouts/guide.html +++ b/_layouts/guide.html @@ -17,9 +17,9 @@

    {{ page.title }}


    diff --git a/assets/frelard_objects_extension.png b/assets/frelard_objects_extension.png index 3986862c..cfac1351 100644 Binary files a/assets/frelard_objects_extension.png and b/assets/frelard_objects_extension.png differ diff --git a/docs/Interaction_Guidelines/ux_build_test.md b/docs/Interaction_Guidelines/ux_build_test.md index 2a163369..b59324c5 100644 --- a/docs/Interaction_Guidelines/ux_build_test.md +++ b/docs/Interaction_Guidelines/ux_build_test.md @@ -6,12 +6,8 @@ layout: guide This section serves as a broad overview of the developer experience and considerations of making extensions. -  - ![lifecycle](./imgs/1-lifecycle.png) -  - ## 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. @@ -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)
    Participate in a community of developers that are passionate about creating extensions. -* [Extension Gallery (beta)](https://extensiongallery.tableau.com/)
    Explore and use some of the extensions our partners have created. +* [Tableau Exchange](https://exchange.tableau.com/)
    Explore and use some of the extensions our partners have created. * [Developer Preview](https://prerelease.tableau.com/extensions-api)
    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. -  - ## 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)**. - -  - ## 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. - ------   +----- 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. - -  - -  - ---- - \ No newline at end of file diff --git a/docs/trex_api_about.md b/docs/trex_api_about.md index e50c2e80..1b48c0bb 100644 --- a/docs/trex_api_about.md +++ b/docs/trex_api_about.md @@ -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). ```xml - + ``` 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. @@ -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); ``` - - - - - - - - diff --git a/docs/trex_configure.md b/docs/trex_configure.md index 5d4334a3..40e393b1 100644 --- a/docs/trex_configure.md +++ b/docs/trex_configure.md @@ -25,7 +25,6 @@ The first step is to add the `` option to the extension's manifest - ``` @@ -36,14 +35,12 @@ This object maps a special ID or key (which must be `'configure'`) to a function with adding a `` 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'; @@ -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 @@ -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. diff --git a/docs/trex_create.md b/docs/trex_create.md index a2fef5ff..ab79c2e4 100644 --- a/docs/trex_create.md +++ b/docs/trex_create.md @@ -31,7 +31,7 @@ For convenience, you might want to create a folder for your "Hello World" dashbo The manifest file (`EXTENSION-NAME.trex`) is an XML file that describes the extension and provides information to register the extension with Tableau. For a description of the contents of this file, see [Elements of the manifest file]({{site.baseurl}}/docs/trex_manifest#elements-of-the-manifest-file). 1. In the `HelloDemo` folder (or where ever you want to put your files), create a manifest file for your extension. -Name the manifest file for your extension (for example, `HelloExtension` and save it with the file name extension `.trex`. +Name the manifest file for your extension (for example, `HelloExtension.trex`). 2. Copy the following XML code into your new file. Make sure that the `` declaration appears as the first element in the file (line 1, column 1). Any blank spaces in front of the declaration will cause an error when you load the extension. @@ -62,24 +62,20 @@ Name the manifest file for your extension (for example, `HelloExtension` and sav ``` - In this file, you need to provide values for a few elements. Some key pieces are: -- For `` use reverse domain name notation to uniquely identify the extension (`com.example.extension.hello.demo`) -- For `` make sure that this specifies the URL of your web application. You must use the HTTPS protocol. The exception to this requirement is `localhost`, where you can use HTTP. For example, if you created a `HelloDemo` folder and want to host the file locally on your computer using port 8765, you might use: `http://localhost:8765/HelloDemo/HelloExtension.html` -- The `` element that specifies the minimum version of the Extensions API library that is required to run the extension. -- For `` you must use a Base64-encoded icon. To use the default icon, copy and paste the `` example here, or copy one of the manifest files (`.trex`) from the samples. -- Provide the `name` for your extension (`Hello Extensions!`). The manifest file can be localized, so provide the name (or names) in the appropriate `` elements in the `` section. - -- After you have created the HTML and JavaScript files for your extension, you use this `.trex` file to add the extension to a Tableau dashboard. To do that, you drag the **Extension** object on to the dashboard. In the **Choose an Extension** dialog box, click **My Extensions** to locate and open the manifest file you just created. - -- For information about the manifest file and about adding version information, see the [Tableau Extension Manifest]({{site.baseurl}}/docs/trex_manifest.html). + - For `` use reverse domain name notation to uniquely identify the extension (`com.example.extension.hello.demo`) + - For `` make sure that this specifies the URL of your web application. You must use the HTTPS protocol. The exception to this requirement is `localhost`, where you can use HTTP. For example, if you created a `HelloDemo` folder and want to host the file locally on your computer using port 8765, you might use: `http://localhost:8765/HelloDemo/HelloExtension.html` + - The `` element that specifies the minimum version of the Extensions API library that is required to run the extension. + - For `` you must use a Base64-encoded icon. To use the default icon, copy and paste the `` example here, or copy one of the manifest files (`.trex`) from the samples. + - Provide the `name` for your extension (`Hello Extensions!`). The manifest file can be localized, so provide the name (or names) in the appropriate `` elements in the `` section. +- After you have created the HTML and JavaScript files for your extension, you use this `.trex` file to add the extension to a Tableau dashboard. To do that, you drag the **Extension** object on to the dashboard. In the **Add an Extension** dialog box, click **Access Local Extensions** to locate and open the manifest file you just created. +- For information about the manifest file and about adding version information, see the [Tableau Extension Manifest File](trex_manifest.md). --- ### Create your web app -The web app you create controls and interacts with the Tableau dashboard objects. The web app consists of one or more HTML files (one is the minimum). You host this web app on a web server (the server specified in the manifest file). - - +The web app you create controls and interacts with the Tableau dashboard objects. The web app consists of one or more HTML files. You host this web app on a web server (the server specified in the manifest file). #### Create the HTML page @@ -97,7 +93,7 @@ Your web application must include an HTML page. This page should link to the Ext - Hello Extensions` + Hello Extensions @@ -107,8 +103,7 @@ Your web application must include an HTML page. This page should link to the Ext - - + @@ -125,24 +120,20 @@ Your web application must include an HTML page. This page should link to the Ext ``` - The sample code includes a link to the JavaScript library (`tableau.extensions.1.latest.js`), which is available in the `/lib` folder. The sample code also includes links to jQuery and Bootstrap libraries. + The sample code also includes links to jQuery and Bootstrap libraries. -3. If necessary, adjust the relative path to the Extensions API JavaScript library (`tableau.extensions.1.latest.js`), which is available in the `/lib` folder. +3. If necessary, adjust the relative path to the Extensions API JavaScript library (`tableau.extensions.1.latest.js`), which is available in the `./lib` folder. ```html - - - + ``` 4. The sample code also includes a link to `hello-extension.js`, this is a JavaScript file that you will need to create. The path assumes that the JavaScript file is in the same directory as your HTML file. Adjust the path and name as necessary and save the file. ```html - - ``` --- @@ -152,38 +143,25 @@ Your web application must include an HTML page. This page should link to the Ext 1. Start the web service to verify you have the web app and files configured.
    The URL of the server must match the `SERVER` in the manifest file for the extension. Be sure to include the `http://` or `https://` in the URL. If you are using your `localhost` for development work, you might want to use the same lightweight web server that is used for the Extensions API samples and tutorial. Assuming that you've cloned or downloaded the repository, and that you've created a folder under `/extensions-api`, you can start the server by using the `npm start` command. Or if you need to use a different port and location, you can install and start the `http-server` yourself (replacing PORT with the port you need): ```bash - - npm install http-server -g && http-server -p PORT - - ``` - -2. Check the HTML page to make sure that your web server is working. Place the URL in the address bar of your browser. This is the URL from the `` you specified in the manifest file. Be sure to include the full path to the web page. - - ```html - - http://localhost:8765/HelloDemo/HelloExtension.html - + npm install http-server -g && http-server -p PORT ``` +2. Check the HTML page to make sure that your web server is working. Place the URL in the address bar of your browser. This is the URL from the `` you specified in the manifest file, for example `http://localhost:8765/HelloDemo/HelloExtension.html`. Be sure to include the full path to the web page. --- ### Test your extension in Tableau -After you have created the manifest file (`.trex`) and have hosted your web app you can test it in Tableau. It's a good idea to do this even if your application isn't completed. - - -1. Start up your web page or application (or make sure it is running). +After you have created the manifest file (`.trex`) and have hosted your web app you can test it in Tableau Desktop. -2. Start Tableau and open a workbook with a dashboard or create a new dashboard. -3. In the dashboard, under **Objects**, select **Extension** and drag it on to the dashboard. In the **Choose an Extension** dialog box, click **My Extensions** and browse to directory where you have your manifest file. +1. Start Tableau and open a workbook with a dashboard or create a new dashboard. +2. In the dashboard, under **Objects**, select **Extension** and drag it on to the dashboard. In the **Add an Extension** dialog box, click **Access Local Extensions** and browse to directory where you have your manifest file. After you select the manifest file, your web page should appear in the dashboard zone. - If not, and you see a 404 error, verify that you specified the correct URL to serve the page in the `.trex` file. - - Tableau parses the `.trex` file when you add the extension to the dashboard. If you make changes to the `.trex` file after you have added it to the dashboard, you need to remove the extension and re-add it. See [What Happens When you Reload an Extension]({{site.baseurl}}/docs/trex_reload.html) - + - Tableau parses the `.trex` file when you add the extension to the dashboard. If you make changes to the `.trex` file after you have added it to the dashboard, click Reload from the extension menu (or remove the extension from the dashboard and re-add it). See [What Happens When you Reload an Extension]({{site.baseurl}}/docs/trex_reload.html). --- @@ -232,9 +210,7 @@ The next step is to create the JavaScript that calls the Extensions API. In your After your extension is installed and showing up in Tableau, you can continue to work on your web application and see the changes without leaving Tableau. 1. Make changes to your HTML and JavaScript files and save those changes. - 2. When you want to see those changes, select the extension in the dashboard. - 3. In the shortcut menu, click **Reload** to refresh and reload the extension in the dashboard. ![alt text]({{site.baseurl}}/assets/extension_reload_menu.png "Shortcut menu showing the Reload option"){:height="25%" width="25%"} @@ -248,8 +224,6 @@ You can also use the Tableau log files to identify issues, see [Use Log files to ## What's next? -- For more information about how you can use the Extensions API, go look at the [Samples](https://github.com/tableau/extensions-api/tree/master/Samples/) or follow the [Tutorial](https://github.com/tableau/extensions-api/tree/master/Tutorial/) and learn how to build a dashboard extension, step by step. +- For more information about how you can use the Extensions API, go look at the [Samples](https://github.com/tableau/extensions-api/tree/main/Samples/) or follow the [Tutorial](https://github.com/tableau/extensions-api/tree/main/Tutorial/) and learn how to build a dashboard extension, step by step. - Get familiar with the programming interface of the Extensions API, see API Reference. - - diff --git a/docs/trex_data_access.md b/docs/trex_data_access.md index 6159f7ba..215b9223 100644 --- a/docs/trex_data_access.md +++ b/docs/trex_data_access.md @@ -83,7 +83,6 @@ If full data is not declared in the manifest file, and the extensions calls one ``` PermissionValidation.ts:26 Extension (name = DataSources Sample, ID = com.tableau.extensions.demo.local) is missing required permission: full-data Error: internal-error: permission-denied: Missing required permission to run get-underlying-data(...) - ``` --- @@ -115,7 +114,6 @@ If a user clicks **Cancel**, the workbook is opened, but the extension is not lo ``` Extension was denied the required permission to run. Permissions approval can be reset through the context menu. - ``` Users can use choose to allow the extension to run by using the clicking **Reset Permissions** from the **More Options** drop-down menu of the layout container. This opens up the **Allow Extensions** dialog box where the user can change permissions for the extension. diff --git a/docs/trex_debug_server.md b/docs/trex_debug_server.md index 81dc7ac7..f987587e 100644 --- a/docs/trex_debug_server.md +++ b/docs/trex_debug_server.md @@ -35,7 +35,7 @@ Under this, you will find the name of the server (for example `localhost`), and ## Set breakpoints and explore the code -If you need to debug your extension, setting a breakpoint in your source code is a good way to get started. When the breakpoint is hit, the code execution is paused in the debugger. You can then use the debugger controls to step through your code. You can use the debugging tools to see the values of local variables, and the call stack. You can also hover over in-scope variables in source window and see the current values. +If you need to debug your extension, setting a breakpoint in your source code is a good way to get started. When the breakpoint is hit, the code execution is paused in the debugger. You can then use the debugger controls to step through your code. You can use the debugging tools to see the values of local variables, and the call stack. You can also hover over in-scope variables in the source window and see the current values. 1. Locate the line in your source code and set the breakpoint.
    For example, you want to set this early in your code after the `initializeAsync()` function call. @@ -46,7 +46,7 @@ You might see the permission dialog box prompt as the extension gets loaded. 3. Step through your code or set other breakpoints.
    You can examine variables to see what information the extension has access to. For example, if you step or stop on the source line where you have access to the dashboard object, you can examine the values of the available resources in the dashboard. - ```javascript/ + ```javascript // To get filter info, first get the dashboard. const dashboard = tableau.extensions.dashboardContent.dashboard; ``` @@ -56,9 +56,7 @@ For example, entering the following in the Console window (while you are paused ```javascript - tableau.extensions.dashboardContent.dashboard.worksheets.forEach(function (worksheet){console.log(worksheet.name)}) - ``` The following screenshot illustrates what your debugging session might look like if you use the Chrome DevTools. A breakpoint was set and the extension's JavaScript code is paused in the debugger. @@ -83,7 +81,7 @@ You might need to click **Continue** many times, as code execution stops for all In Tableau Desktop, there is a debugging option you can set to pause the extension when it is loading. For more information, see [Debugging loading and initialization issues]({{site.baseurl}}/docs/trex_debugging.html#debugging-loading-and-initialization-issues). -If your extension fails to load at all on Tableau Server or Tableau Online, check the console window of the debugger to see if there is an error message of some kind. The console messages can give you clues about where to begin investigating when something goes wrong. If the error is caused by mixed content (trying to load an HTTP web page inside of a secure HTTPS server), see [Load and view localhost content on sites that use secure connections]({{site.baseurl}}/docs/trex_debug_server.html#load-and-view-localhost-content-on-sites-that-use-secure-connections). +If your extension fails to load at all on Tableau Server or Tableau Online, check the console window of the debugger to see if there is an error message of some kind. The console messages can give you clues about where to begin investigating when something goes wrong. If the error is caused by mixed content (trying to load an HTTP web page inside of a secure HTTPS server), see the next section. --- @@ -100,10 +98,8 @@ To temporarily get around these safety settings for the session, you can click t ![alt text]({{site.baseurl}}/assets/online_blocked_extension.png "Chrome browser showing alert when extension running on a localhost server") -During the session, anytime you refresh or reload the web page, you will see the extensions dialog box requesting permission to run. And in the debugger console, you might see a warning message about mixed content. +During the session, any time you refresh or reload the web page, you will see the extensions dialog box requesting permission to run. And in the debugger console, you might see a warning message about mixed content. ``` Mixed Content: The page at 'https:/some_URLs#4' was loaded over HTTPS, but requested an insecure resource 'http://localhost:8765/Samples/Filtering/filtering.html'. This content should also be served over HTTPS. - ``` - diff --git a/docs/trex_debugging.md b/docs/trex_debugging.md index 59bd336c..697789f2 100644 --- a/docs/trex_debugging.md +++ b/docs/trex_debugging.md @@ -44,7 +44,7 @@ Latest maintenance release of 2020.2.7+, 2020.3.6+, 2020.4.2+ | 87.0.4280 | Chro * [Chromium for macOS (`chrome-mac.zip`) (79.0.3945.0)](https://commondatastorage.googleapis.com/chromium-browser-snapshots/index.html?prefix=Mac/706915/) -
    Note If you are using Tableau 2021.1, or the latest maintenance releases of Tableau 2020.2.2.7+, 2020.3.3.6+, and 2020.4.2+, you can use Chrome version 80 (or later) for debugging your extension.
    +
    Note If you are using Tableau 2021.1 or newer, or the latest maintenance releases of Tableau 2020.2.2.7+, 2020.3.3.6+, and 2020.4.2+, you can use Chrome version 80 (or later) for debugging your extension.
    --- @@ -55,7 +55,7 @@ Latest maintenance release of 2020.2.7+, 2020.3.6+, 2020.4.2+ | 87.0.4280 | Chro 1. Exit Tableau if it is already running on your computer. 2. Open a Command Prompt window. 2. Start Tableau using the following command. -
    Replace `` with the version of Tableau you are using (for example, `Tableau 2018.3`). +
    Replace `` with the version of Tableau you are using (for example, `Tableau 2021.4`). ``` "C:\Program Files\Tableau\Tableau \bin\tableau.exe" --remote-debugging-port=8696 @@ -83,11 +83,10 @@ If you open the file location, you can create a new shortcut to `Tableau.exe` (c 1. Open a Terminal window. 2. Start Tableau using the following command. -
    Replace `` with the version of Tableau you are using (for example,`2018.3.app`). +
    Replace `` with the version of Tableau you are using (for example,`2021.4.app`). ``` open /Applications/Tableau\ Desktop\ .app --args --remote-debugging-port=8696 - ``` This command enables remote debugging of extensions for this session of Tableau. @@ -115,22 +114,21 @@ Note that you can only debug one extension, or instance of an extension, at a ti --- -## Debugging loading and initialization issues (Tableau 2021.1 and later) +## Debugging loading and initialization issues + +### Tableau 2021.1 and later If you need to troubleshoot or debug issues that prevent your extension from loading or initializing, you can set breakpoints that trigger when your JavaScript code is loaded. 1. Start the debugging session as described in [Debugging Tableau Desktop using Chrome/Chromium](#debugging-tableau-desktop-using-chromechromium). - -1. Click the **Sources** tab in Chrome/Chromium, under **Event Listener Breakpoints**, click **Script** and enable the **Script First Statement** breakpoint. You just have to do this one time. - -1. In Tableau Desktop, select the extension in the dashboard and click **Reload** from the **More Options** shortcut menu.
    +2. Click the **Sources** tab in Chrome/Chromium, under **Event Listener Breakpoints**, click **Script** and enable the **Script First Statement** breakpoint. You just have to do this one time. +3. In Tableau Desktop, select the extension in the dashboard and click **Reload** from the **More Options** shortcut menu.
    The debugger will pause each time the first statement of a script runs, allowing you to debug the startup process. - -1. To get to your JavaScript code, click **Continue** several times. After your JavaScript is loaded, you can set a breakpoint in your startup code. +4. To get to your JavaScript code, click **Continue** several times. After your JavaScript is loaded, you can set a breakpoint in your startup code. --- -## Debugging loading and initialization issues (Tableau 2020.4 and earlier) +### Tableau 2020.4 and earlier It can be difficult to hit breakpoints that occur during the loading of your page because of the remote debugging process, and because of the way loading was handled prior to Tableau 2021.1. To help with this, you can select a menu option that causes your extension to wait to load until you trigger it to proceed. diff --git a/docs/trex_error_handling.md b/docs/trex_error_handling.md index c1a8fa98..dc04f2fe 100644 --- a/docs/trex_error_handling.md +++ b/docs/trex_error_handling.md @@ -20,14 +20,13 @@ As you create your extension, you want to be sure to catch potential error condi ## Handle extensions.ui dialog box errors -For an example of how to handle an extension dialog box error, see the [UINamepace](https://github.com/tableau/extensions-api/tree/master/Samples/UINamepace?=target="_blank") sample. The sample shows how you could handle the error condition that occurs if a user dismisses a modal dialog box (`DialogClosedByUser`). In this extension, the user is expected to click the **Start Auto Refresh** button, which saves the configuration settings and closes the dialog box, by calling the `tableau.extensions.ui.closeDialog()` method with the return payload. If a user clicks the dialog box control (the **X** in the upper-right corner) instead, the error occurs. The following snippet illustrates how you could handle this error: +For an example of how to handle an extension dialog box error, see the [UINamespace](https://github.com/tableau/extensions-api/tree/main/Samples/UINamespace) sample. The sample shows how you could handle the error condition that occurs if a user dismisses a modal dialog box (`DialogClosedByUser`). In this extension, the user is expected to click the **Start Auto Refresh** button, which saves the configuration settings and closes the dialog box, by calling the `tableau.extensions.ui.closeDialog()` method with the return payload. If a user clicks the dialog box control (the **X** in the upper-right corner) instead, the error occurs. The following snippet illustrates how you could handle this error: ```javascript - tableau.extensions.ui.displayDialogAsync(args... ).then((args... ) => { // // code that sets up the extension in the modal dialog box - // + // }).catch((error) => { // One expected error condition is when the popup is closed by the user // (meaning the user clicks the 'X' in the top right of the dialog). @@ -40,7 +39,4 @@ tableau.extensions.ui.displayDialogAsync(args... ).then((args... ) => { console.error(error.message); } }); - ``` - - diff --git a/docs/trex_events.md b/docs/trex_events.md index 03c57dc3..b885626a 100644 --- a/docs/trex_events.md +++ b/docs/trex_events.md @@ -44,5 +44,4 @@ In most cases, you can create an event listener by chaining the methods to the s // ... ``` -For more information, check out the sample extension, Filtering. - +For more information, check out the sample extension, [Filtering](https://github.com/tableau/extensions-api/tree/main/Samples/Filtering). diff --git a/docs/trex_examples.md b/docs/trex_examples.md index 1107427c..c30024ea 100644 --- a/docs/trex_examples.md +++ b/docs/trex_examples.md @@ -6,9 +6,9 @@ layout: docs The best way to learn how to build your own extensions is to look at the sample code. To examine the sample source files to see how Tableau dashboard extensions work, you can clone or download the [Extensions API](https://github.com/tableau/extensions-api) SDK on GitHub and run the samples or the tutorial. - To download the Extensions API SDK, if you have not already done so, see [Get Started]({{ site.baseurl }}/docs/trex_getstarted.html). -- You can browse the sample code for the dashboard extensions in the [Samples](https://github.com/tableau/extensions-api/tree/master/Samples?=target="_blank") and the [Tutorial](https://github.com/tableau/extensions-api/tree/master/Tutorial?=target="_blank") folders on GitHub. +- You can browse the sample code for the dashboard extensions in the [Samples](https://github.com/tableau/extensions-api/tree/main/Samples?=target="_blank") and the [Tutorial](https://github.com/tableau/extensions-api/tree/main/Tutorial?=target="_blank") folders on GitHub. -- You can also create dashboard extensions using TypeScript. See the TypeScript sample code in [Samples-TypeScript](https://github.com/tableau/extensions-api/tree/master/Samples-Typescript?=target="_blank") on GitHub. +- You can also create dashboard extensions using TypeScript. See the TypeScript sample code in [Samples-TypeScript](https://github.com/tableau/extensions-api/tree/main/Samples-Typescript?=target="_blank") on GitHub. - You can also check out the dashboard extensions from the community, see [Community Extensions]({{ site.baseurl }}/community/). @@ -32,37 +32,37 @@ The following instructions assume that you have already downloaded and extracted The dashboard extension samples are in the `Samples` folder. There is also a step-by-step tutorial you can follow in the `Tutorial` folder. -The [Samples-Typescript](https://github.com/tableau/extensions-api/tree/master/Samples-Typescript?=target="_blank") folder shows how you can use the Extensions API type definitions to create extensions in TypeScript. For more information, see [Use TypeScript with the Extensions API]({{site.baseurl}}/docs/trex_typescript.html). +The [Samples-Typescript](https://github.com/tableau/extensions-api/tree/main/Samples-Typescript?=target="_blank") folder shows how you can use the Extensions API type definitions to create extensions in TypeScript. For more information, see [Use TypeScript with the Extensions API]({{site.baseurl}}/docs/trex_typescript.html). -- **[DataSources](https://github.com/tableau/extensions-api/tree/master/Samples/DataSources?=target="_blank")** +- **[DataSources](https://github.com/tableau/extensions-api/tree/main/Samples/DataSources?=target="_blank")** Shows how to use the `getDataSourcesAsync` function to find the names of the data sources for each worksheet in the dashboard. Like the Filtering sample, the DataSources sample makes use the `Promise.all` function to combine the promises from the asynchronous calls together, and then waits for them to resolve. -- **[Filtering](https://github.com/tableau/extensions-api/tree/master/Samples/Filtering?=target="_blank")** +- **[Filtering](https://github.com/tableau/extensions-api/tree/main/Samples/Filtering?=target="_blank")** Demonstrates how to use the `getFiltersAsync` function to find and display the active filters in the dashboard and calls the `addEventListener` function to set a `FilterChanged` event on each workbook in the dashboard. Any time a filter value is changed, the extension refreshes the table that displays the active filters. -- **[Parameters](https://github.com/tableau/extensions-api/tree/master/Samples/Parameters?=target="_blank")** +- **[Parameters](https://github.com/tableau/extensions-api/tree/main/Samples/Parameters?=target="_blank")** Finds and displays all the parameters in the dashboard and then sets an event listener that waits for a parameter to change, which triggers a refresh. -- **[Settings](https://github.com/tableau/extensions-api/tree/master/Samples/Settings?=target="_blank")** +- **[Settings](https://github.com/tableau/extensions-api/tree/main/Samples/Settings?=target="_blank")** Uses the `settings` namespace to save settings (key-value pairs) for the extension. Demonstrates how you can save settings for each instance of an extension, which enables sharing common views of a workbook. -- **[UINamespaces](https://github.com/tableau/extensions-api/tree/master/Samples/UINamespace?=target="_blank")** +- **[UINamespaces](https://github.com/tableau/extensions-api/tree/main/Samples/UINamespace?=target="_blank")** Demonstrates how you can use the `UI` namespace to create a modal dialog box (or popup) that runs another extension, which allows users to interact and change the settings for the parent extension. This sample controls the background auto-refresh interval for data sources in a dashboard. -- **[Tutorial](https://github.com/tableau/extensions-api/tree/master/Tutorial?=target="_blank")** +- **[Tutorial](https://github.com/tableau/extensions-api/tree/main/Tutorial?=target="_blank")** Walks you through the step-by-step process of creating and refining an extension that displays a summarized table of the currently selected marks. -- **[Samples-Typescript](https://github.com/tableau/extensions-api/tree/master/Samples-Typescript?=target="_blank")** +- **[Samples-Typescript](https://github.com/tableau/extensions-api/tree/main/Samples-Typescript?=target="_blank")** The **Samples-Typescript** folder shows how you can use the Extensions API type definitions to create extensions in TypeScript. The sample extensions include TypeScript versions of many of the JavaScript samples. For more information, see [Use the TypeScript samples](#use-the-typescript-samples) and [Use TypeScript with the Extensions API]({{site.baseurl}}/docs/trex_typescript.html). @@ -70,9 +70,9 @@ The [Samples-Typescript](https://github.com/tableau/extensions-api/tree/master/S Shows how you can use Tableau Viz to add visualizations to your dashboard extensions. This sample demonstrates the effects of different mark types and color palettes. For more information about Tableau Viz, see [Add Tableau Viz to Your Dashboard Extensions]({{site.baseurl}}/docs/trex_tableau_viz.html). -**[Formatting](https://github.com/tableau/extensions-api/tree/main/Samples/Formatting?=target="_blank")** +- **[Formatting](https://github.com/tableau/extensions-api/tree/main/Samples/Formatting?=target="_blank")** - Shows how you can access the CSS formatting in the Tableau workbook and apply it to the HTML elements in your dashboard extension. Create a consistent look and feel across the extension and the dashboard. + Shows how you can access the CSS formatting in the Tableau workbook and apply it to the HTML elements in your dashboard extension. Create a consistent look and feel across the extension and the dashboard. --- @@ -114,7 +114,6 @@ The port you use for the web server also has to match the port specified in the http://localhost:PORT/samples/parameters/parameters.html - ``` --- @@ -125,7 +124,7 @@ After you start the web server to host the sample extensions, you can try the ex 1. Start Tableau and open a workbook that has a dashboard, or open a workbook and create a new dashboard. 2. In the dashboard, under **Objects**, select **Extension** and drag it on to the dashboard. 3. In the **Choose an Extension** dialog box, click **My Extensions**. -4. Browse to the directory where the samples are located. For example, if you downloaded or cloned the GitHub repository, go to `\extensions-api\Samples`. +4. Browse to the directory where the samples are located. For example, if you downloaded or cloned the GitHub repository, go to `extensions-api\Samples`. 5. Select one of the folders for the samples and open the `.trex` file (for example, `DataSources.trex`).
    Every Tableau extension has a manifest file (`.trex`) that describes the extension and identifies the location of the web application. @@ -145,12 +144,12 @@ The TypeScript samples show how you can write your source code in TypeScript and 3. Build the TypeScript samples: ``` - npm run build + npm run build ``` Run lint with the semistandard package. ``` - npm run lint + npm run lint ``` 4. Compile and start the HTTP server for the extensions. This command also watches the source file directories and automatically builds the samples when you make changes. diff --git a/docs/trex_getdata.md b/docs/trex_getdata.md index d208f319..6e6dd6a1 100644 --- a/docs/trex_getdata.md +++ b/docs/trex_getdata.md @@ -51,20 +51,18 @@ You can also get the data from the selected marks in the worksheet, or the marks The first step for accessing data of any kind is to get the worksheet object (or objects) that you want. ```javascript +// After initialization, ask Tableau what sheets are available +const worksheets = tableau.extensions.dashboardContent.dashboard.worksheets; - // After initialization, ask Tableau what sheets are available - const worksheets = tableau.extensions.dashboardContent.dashboard.worksheets; - - // Find a specific worksheet - var worksheet = worksheets.find(function (sheet) { - return sheet.name === "Name of Worksheet I want"; - }); - - // Or iterate through the array of worksheets - worksheets.forEach(function (worksheet) { - // process each worksheet... - }); +// Find a specific worksheet +var worksheet = worksheets.find(function (sheet) { + return sheet.name === "Name of Worksheet I want"; +}); +// Or iterate through the array of worksheets +worksheets.forEach(function (worksheet) { + // process each worksheet... +}); ``` After you have a worksheet object, you can call one of the methods to access the data for that worksheet. For summary data, or the data from the selected or highlighted marks, the steps are straight forward. If you want access the underlying data (or full data), there are additional steps and considerations. See [Accessing Underlying Data]({{site.baseurl}}/docs/trex_data_access.html). @@ -73,16 +71,14 @@ After you have a worksheet object, you can call one of the methods to access the ## Get summary data from a worksheet ```javascript +// get the summary data for the sheet +worksheet.getSummaryDataAsync().then(function (sumdata) { - // get the summary data for the sheet - worksheet.getSummaryDataAsync().then(function (sumdata) { - - const worksheetData = sumdata; - // The getSummaryDataAsync() method returns a DataTable - // Map the DataTable (worksheetData) into a format for display, etc. - - }); +const worksheetData = sumdata; +// The getSummaryDataAsync() method returns a DataTable +// Map the DataTable (worksheetData) into a format for display, etc. +}); ``` ## Get full data from a worksheet @@ -104,7 +100,6 @@ The first step is to use the `Worksheet.getUnderlyingTablesAsync()` method to re To get the underlying data for each logical table, you use the `LogicalTable.id` property of the table to call `Worksheet.getUnderlyingTableDataAsync()`. Note that when you use the `getUnderlyingTablesAsync()` in Tableau 2020.1 and earlier, the method will only return a single table, and that table uses `single-table-id-sentinel` as the `LogicalTable.id`. ```javascript - // Call to get the underlying logical tables used by the worksheet worksheet.getUnderlyingTablesAsync().then(logicalTables => { // Get the first logical table's id @@ -115,8 +110,6 @@ worksheet.getUnderlyingTablesAsync().then(logicalTables => { // by calling worksheet.getUnderlyingTableDataAsync(logicalTableId) }); - - ``` #### 2. Get data from the logical table(s) using getUnderlyingTableDataAsync() @@ -124,14 +117,12 @@ worksheet.getUnderlyingTablesAsync().then(logicalTables => { The following example returns data for the first logical table that is used by a worksheet called *"Sale Map"*. ```javascript - var worksheet = tableau.extensions.dashboardContent.dashboard.worksheets.find(w => w.name === "Sale Map"); worksheet.getUnderlyingTablesAsync().then(logicalTables => { worksheet.getUnderlyingTableDataAsync(logicalTables[0].id).then(dataTable => { // process the dataTable... }); }); - ``` --- @@ -143,7 +134,6 @@ If you want your extension to work in all versions of Tableau, you should use th ```javascript - // the following example uses the Superstore workbook and gets the underlying data // for a specific worksheet. // The example writes the values for a single column (states names) to the console. tableau.extensions.dashboardContent.dashboard.worksheets.find(w => w.name === "Sale Map").getUnderlyingDataAsync().then(dataTable => { @@ -155,8 +145,6 @@ tableau.extensions.dashboardContent.dashboard.worksheets.find(w => w.name === "S let values = list.filter((el, i, arr) => arr.indexOf(el) === i); console.log(values) }); - - ``` # Get data from a data source @@ -165,7 +153,6 @@ You can also get the underlying data from the data sources for the worksheet. To Just like worksheet methods that access full data, the following methods for the data source also require that your extension specifies `full data` permissions in the `trex` file. See [Add permissions to access full data to manifest file]({{ site.baseurl }}/docs/trex_data_access.html#add-permissions-to-access-full-data-to-manifest-file). - | Method | Tableau Version | Extensions API Library | Status | |:------ | :---------------| :--------------------- | | `Datasource.getConnectionSummariesAsync()`| Tableau 2018.2 and later | version 1.1 and later | Current | @@ -176,19 +163,15 @@ Just like worksheet methods that access full data, the following methods for the | `Datasource.getLogicalTableDataAsync()` | Tableau 2018.2 and later | version 1.4 and later | Current | - ## Get the data sources from a worksheet To get the data sources a worksheet uses, you call the `getDataSourcesAsync()` method on the worksheet object. The following code snippet shows how you might select a specific data source of a worksheet. ```javascript - tableau.extensions.dashboardContent.dashboard.worksheets.find(w => w.name === "Sale Map").getDataSourcesAsync().then(datasources => { let dataSource = datasources.find(datasource => datasource.name === "Sample - Superstore"); // return dataSource for further processing }); - - ``` ## Get full data from a worksheet using the v1.4 library (and later) @@ -204,7 +187,6 @@ To get the underlying data for each logical table, use the `LogicalTable.id` pro Example using a single table: ```javascript - // Call to get the logical tables used by the worksheet dataSource.getLogicalTablesAsync().then(logicalTables => { // Get the first logical table's id @@ -213,16 +195,12 @@ dataSource.getLogicalTablesAsync().then(logicalTables => { // Use the logicalTableId to then get worksheet's underlying data // by calling worksheet.getUnderlyingTableDataAsync(logicalTableId) - }); - - ``` Example that writes the names of all the logical tables in the data source to the console: ```javascript - // Call to get the logical tables used by the worksheet dataSource.getLogicalTablesAsync().then(logicalTables => { // Loop through each table in this data source @@ -230,8 +208,6 @@ dataSource.getLogicalTablesAsync().then(logicalTables => { console.log(table.caption); }); }); - - ``` #### 2. Get data from the logical table(s) using getLogicalTableDataAsync() @@ -241,19 +217,17 @@ The following example returns the column names of the first logical table that i ```javascript - - dataSource.getLogicalTablesAsync().then(logicalTables => { - // get the underlying data from the first logical table - dataSource.getLogicalTableDataAsync(logicalTables[0].id).then(dataTable => { - // get the names of the columns in the dataTable - let list = []; - for (let col of dataTable.columns) { - list.push(col.fieldName); - } - console.log(list); - }); +dataSource.getLogicalTablesAsync().then(logicalTables => { + // get the underlying data from the first logical table + dataSource.getLogicalTableDataAsync(logicalTables[0].id).then(dataTable => { + // get the names of the columns in the dataTable + let list = []; + for (let col of dataTable.columns) { + list.push(col.fieldName); + } + console.log(list); }); - +}); ``` @@ -264,14 +238,12 @@ If you were using 1.3 version of the Extensions API library (or earlier), you ha If you want your extension to work in all versions of Tableau, you should use the latest library (version 1.4 or later) and the `Datasource.getLogicalTablesAsync()` and `Datasource.getLogicalTableDataAsync` methods. ```javascript - tableau.extensions.dashboardContent.dashboard.worksheets.find(w => w.name === "Sale Map").getDataSourcesAsync().then(datasources => { dataSource = datasources.find(datasource => datasource.name === "Sample - Superstore"); return dataSource.getUnderlyingDataAsync(); }).then(dataTable => { // process the dataTable... }); - ``` --- @@ -330,7 +302,6 @@ Worksheet.getUnderlyingTableDataAsync(logicalTables[0].id).then(function(success // called on any error, such as when the extension // doesn’t have full data permission }); - ``` An error is also printed to the console. If you use any of these methods to get the full data, be sure to add error handling for the promise in case of failure. diff --git a/docs/trex_getstarted.md b/docs/trex_getstarted.md index 23ecdb2c..ea0abfdd 100644 --- a/docs/trex_getstarted.md +++ b/docs/trex_getstarted.md @@ -9,7 +9,7 @@ The Tableau Dashboard Extensions API allows developers to create extensions for This section will take you through the process of setting up your environment to use one of the sample dashboard extensions. Using one of the sample extensions is a great way to learn and great way to get started developing your own extensions. In this section, you will start a simple web server on your computer to host the sample. You can use the same process for hosting the extension when you start developing your own. -

    Note If you are looking for information about how to add an extension to a dashboard in Tableau, see Use Dashboard Extensions. If you are looking for extensions that you can use, see the Tableau Extension Gallery.

    +

    Note If you are looking for information about how to add an extension to a dashboard in Tableau, see Use Dashboard Extensions. If you are looking for extensions that you can use, see the Tableau Exchange.

    @@ -27,8 +27,6 @@ A Tableau extension consists of a manifest file (`.trex`), a web page that uses --- - - ### What you need to get started If you want to create an extension or work with the sample code, make sure you have the following dependencies installed: @@ -91,16 +89,16 @@ To use the dashboard extension samples, you need to start up a web server on you --- ### Start Tableau and add an extension to the dashboard -1. Start Tableau and open a workbook that has a dashboard, or open a workbook and create a new dashboard. +1. Start Tableau and open a workbook that has a dashboard, or open a workbook and create a new dashboard with at least one worksheet. 2. In the dashboard, under **Objects**, select **Extension** and drag it on to the dashboard. - ![]({{site.baseurl}}/assets/frelard_objects_extension.png){:height="25%" width="25%"} + ![]({{site.baseurl}}/assets/frelard_objects_extension.png) 3. In the **Choose an Extension** dialog box, click **My Extensions**. Every Tableau extension has a manifest file (`.trex`) that describes the extension and identifies the location of the web application. -4. Browse to the directory where the samples are located. For example, if you downloaded or cloned the GitHub repository, go to `\extensions-api\Samples\DataSources`. +4. Browse to the directory where the samples are located. For example, if you downloaded or cloned the GitHub repository, go to `extensions-api\Samples\DataSources`. 5. Open the `DataSources.trex` file. The sample extension (web application) appears in the dashboard frame. The DataSources sample finds and displays the data source for each worksheet in the dashboard. @@ -115,7 +113,7 @@ To use the dashboard extension samples, you need to start up a web server on you Looking at the files that make up an extension will give you an idea of how an extension is constructed. -1. Browse to the directory where the DataSources sample is located. For example, if you downloaded or cloned the GitHub repository, go to `\extensions-api\Samples\DataSources`. +1. Browse to the directory where the DataSources sample is located. For example, if you downloaded or cloned the GitHub repository, go to `extensions-api\Samples\DataSources`. 2. Open the `datasources.html` file in your favorite Text or Code editor. This HTML page provides the interface that users see when they load the extension. This file includes links to the Extensions API library file and to the file that contains all the JavaScript code for the extension. @@ -127,7 +125,7 @@ Looking at the files that make up an extension will give you an idea of how an e ``` -3. Open the `datasources.js` file. This file contains code to initialize the Extensions API, and contains functions to gather all the data sources used by the workbooks in the dashboard. Read through the code and the code comments to get an understanding about how this extension works. The Extensions API makes use of JavaScript Promises to collect the data returned from the asynchronous function calls. Look for the code that initializes the extension. An extension will often place the initialization code in the JQuery `$(document).ready()` function so that it will run when the page is loaded. +3. Open the `datasources.js` file. This file contains code to initialize the Extensions API, and contains functions to gather all the data sources used by the worksheets in the dashboard. Read through the code and the code comments to get an understanding about how this extension works. The Extensions API makes use of JavaScript Promises to collect the data returned from the asynchronous function calls. Look for the code that initializes the extension. An extension will often place the initialization code in the JQuery `$(document).ready()` function so that it will run when the page is loaded. ```javascript (function () { @@ -173,9 +171,9 @@ You can add multiple instances of an extension to a dashboard or to multiple das ## What's next? -* Start developing your extension by modifying an existing sample. See [samples (GitHub)](https://github.com/tableau/extensions-api/tree/master/Samples/). If you cloned or downloaded the repository, create a copy of the Samples directory. For example, if you make the copy in `\extensions-api\` directory, and call it `MySamples`, you just need to modify the URL in the `.trex` files so that you host the extensions using the same web server you created with `npm start` command. +* Start developing your extension by modifying an existing sample. See [samples (GitHub)](https://github.com/tableau/extensions-api/tree/main/Samples/). If you cloned or downloaded the repository, create a copy of the Samples directory. For example, if you make the copy in `extensions-api\` directory, and call it `MySamples`, you just need to modify the URL in the `.trex` files so that you host the extensions using the same web server you created with `npm start` command. -* Follow the [Tutorial (GitHub)](https://github.com/tableau/extensions-api/tree/master/Tutorial) and learn how to build a dashboard extension, step by step. If you downloaded or cloned the repository, look in the `Tutorial` folder on your computer. +* Follow the [Tutorial (GitHub)](https://github.com/tableau/extensions-api/tree/main/Tutorial) and learn how to build a dashboard extension, step by step. If you downloaded or cloned the repository, look in the `Tutorial` folder on your computer. * For information about creating a simple "Hello World" Tableau extension, see [Create a "Hello World" Dashboard Extension]({{site.baseurl}}/docs/trex_create.html). diff --git a/docs/trex_logging.md b/docs/trex_logging.md index 116cace5..dd4bf903 100644 --- a/docs/trex_logging.md +++ b/docs/trex_logging.md @@ -16,21 +16,13 @@ Support for extensions is built-in to Tableau, so there is nothing you need to s ## Locate the Tableau log files -By default, the Tableau Desktop log file (`log.txt`) is are stored in the following location: - -``` -Users//Documents/My Tableau Repository - -``` -The `log.txt` file contains information about dashboard extension registration and information about extension command execution. +By default, the Tableau Desktop log file (`log.txt`) is stored under `Users//Documents/My Tableau Repository`. The log file contains information about dashboard extension registration and information about extension command execution. ## Download and install the Tableau Log Viewer The Tableau Log Viewer is an open source tool that makes it easier to read Tableau log files. You can install the Log Viewer by downloading a `.zip` file for either Windows or MacOS. If you want to build the Tableau Log Viewer yourself, you can also download or clone the Log Viewer repository. - 1. Download the latest release in the [Releases Section](https://github.com/tableau/tableau-log-viewer/releases){:target="_blank"} of the [Tableau Log Viewer](https://github.com/tableau/tableau-log-viewer){:target="_blank"} repository on GitHub. - 2. Extract `.zip` file on your local computer. Launch the Log Viewer application (`Log Viewer.exe` on Windows, or `Log Viewer.app` on MacOS). 3. Open the log file from the File menu, or drag and drop the Tableau log file into the Log Viewer window. @@ -42,7 +34,7 @@ The Desktop Tableau log file (`log.txt`) is a JSON formatted file. The extension ```json {"ts":"2017-11-27T17:55:55.665", - pid":12100,"tid":"3d08","sev":"info","req":"-", + "pid":12100,"tid":"3d08","sev":"info","req":"-", "sess":"-", "site":"{FA6345B5-D64A-4ADB-9435-12F170D9B2AB}", "user":"-", @@ -92,7 +84,6 @@ The extensions manifest file (`.trex`) is an XML-based file. As part of the regi ```xml Error: Registration Failed: XSD Validation Failed file: Sample.trex - ``` Each XSD validation error in the file is logged separately, which makes it easier to locate and fix problems. For example, the following error shows the exact line number and location where the error occurred. In this case, the value for `extension-version` number was left blank `""`. @@ -118,7 +109,6 @@ When no errors are found with the manifest file, Tableau completes the registrat Event: Extension Successfully Registered id: com.tableau.extensions.dashboard.tutorial.final name: Tutorial - Complete - ``` You can use the `id` of the extension, in this case `com.tableau.extensions.dashboard.tutorial.final` to search for instances where the extension is used. @@ -141,7 +131,6 @@ Event: Executing Command: initialize-add-in-instance id: com.tableau.extensions.dashboard.tutorial.final instance-id: com.tableau.extensions.dashboard.tutorial.final name: Tutorial - Complete - ``` A key part of this is that the extension is assigned an `add-in-instance-id`. This instance id is something you can use to further track activity. @@ -164,7 +153,7 @@ name: Tutorial - Complete In this case, the selection was the name of a worksheet ("Sale Map"). ``` - args: tabdoc:save-add-in-settings add-in-locator-pres-model={"add-in-instance-id": "36C4012514F042DB8F2AB466B445726A","sheet-path":{"sheet-name": "Overview","is-dashboard": true}} add-in-settings={"sheet":"Sale Map"} +args: tabdoc:save-add-in-settings add-in-locator-pres-model={"add-in-instance-id": "36C4012514F042DB8F2AB466B445726A","sheet-path":{"sheet-name": "Overview","is-dashboard": true}} add-in-settings={"sheet":"Sale Map"} name: tabdoc:save-add-in-settings ``` diff --git a/docs/trex_manifest.md b/docs/trex_manifest.md index c9e31106..4fbbf991 100644 --- a/docs/trex_manifest.md +++ b/docs/trex_manifest.md @@ -5,9 +5,6 @@ layout: docs The extension manifest file (`.trex`) contains metadata for the extension and is used for registration. -For details about a manifest or its fields, see the [Sample Manifest File](#sample-manifest-file) and [Elements of the Manifest File](#elements-of-the-manifest-file). - - **In this section** * TOC @@ -30,33 +27,33 @@ At start up, Tableau checks the manifest file. If any errors are found while par ## Sample Manifest File ```xml - - - - en_US - - Extension Description - - 1.0 - - SCHEME://SERVER[:PORT][/PATH] - - Base64-Encoded ICON - - full data - - - - - - - - name in English - name in French - name in German - - - + + + + en_US + + Extension Description + + 1.0 + + SCHEME://SERVER[:PORT][/PATH] + + Base64-Encoded ICON + + full data + + + + + + + + name in English + name in French + name in German + + + ``` diff --git a/docs/trex_oauth.md b/docs/trex_oauth.md index 14d32d6f..2033fdd8 100644 --- a/docs/trex_oauth.md +++ b/docs/trex_oauth.md @@ -68,39 +68,32 @@ One way to manage OAuth sign in for your dashboard extension is to employee web In the OAuth sample, when the extension loads in the dashboard, a unique socket session ID is generated. The socket instance is assigned a random 20-character identifier (`socket.id`). This code is on the client-side, the extension's web page (`index.js`). The code also initializes the sign-in button on the extension's home page. ```javascript - const socket = io(); -// Wait to make sure you've made the socket connection so when you press the button there is a socket ID available to send with the request +// Wait to make sure you've made the socket connection so when you press +// the button there is a socket ID available to send with the request socket.on("connect", () => { $("#submit").prop("disabled", false); }); - - ``` On the Express server (`server.js`), in addition to serving the web pages, the server initializes `socket.io`. ```javascript - const express = require("express"); const app = express(); const server = require("http").createServer(app); const io = require("socket.io")(server); const fetch = require("node-fetch"); - - ``` - - ### Sign in and get the authorization code When a user clicks the sign-in button, it opens a new window or tab in the user's native browser (`window.open`) passing with it the client ID and the socket session ID (`socket.id`). In this example, the URL goes to the authorization endpoint on Spotify and specifies the authorization code response type. Note that this sample uses the client ID for the OAuth sample project on Glitch. You need to change this to match your client ID for your dashboard extension. The method also provides a redirect URL back to the server, where the response will return the authorization code. ```javascript - -// Open a new window to manage the OAuth process outside of Desktop, passing the socket ID so the broker knows where to return the token +// Open a new window to manage the OAuth process outside of Desktop, +// passing the socket ID so the broker knows where to return the token function openSignInWindow() { const scopes = "user-top-read"; const redirect_uri = "https://datadev-oauth-sign-in.glitch.me/complete"; @@ -115,8 +108,6 @@ function openSignInWindow() { socket.id; window.open(url, "_blank"); } - - ``` ### Request the access token (server-side) @@ -151,9 +142,6 @@ app.get("/complete", async (req, res) => { io.to(sessionid).emit("signedin", data.access_token); res.sendFile(__dirname + "/views/complete.html"); }); - - - ``` ### Pass the access token to the client and make requests @@ -161,7 +149,6 @@ app.get("/complete", async (req, res) => { In response to the `signedin` event, the client checks to see if the OAuth access token was received. If the token is present, the client stores it locally and then uses the access token to make a new request to retrieve the user's top artist from Spotify. In case of error, the access token is removed from local storage and the user is asked to sign in again. ```javascript - socket.on("signedin", function(token) { if (token) { localStorage.setItem("spotifyAuth", token); @@ -196,7 +183,6 @@ function updateTopArtist(data) { $("#signIn").hide(); $("#name").html("" + data.items[0].name + " is your favorite artist!"); } - ``` ### Next steps diff --git a/docs/trex_overview.md b/docs/trex_overview.md index b9d53eaa..143dd3d8 100644 --- a/docs/trex_overview.md +++ b/docs/trex_overview.md @@ -30,24 +30,19 @@ Plenty! Using the Extensions API, you can create dashboard extensions that enabl The Extensions API is a JavaScript library that you link to from your web application. The Extensions API library (`tableau.extensions.n.n.n.js`) gives your application access to Tableau dashboard content, including worksheets, filters, marks, and parameters. In your JavaScript code, you can set up event listeners to get notified when events occur on the dashboard. You can use the Extensions API to apply filters, or to get data back from selected marks in a worksheet. -For more information about how you can use Extensions API, go look at the [Samples](https://github.com/tableau/extensions-api/tree/master/Samples/). +For more information about how you can use Extensions API, go look at the [Samples](./trex_examples.md). ## Comparing the Extensions API and the Embedding JavaScript API -The Extensions API and the Embedding JavaScript API (also known as the [JavaScript API](https://onlinehelp.tableau.com/current/api/js_api/en-us/JavaScriptAPI/js_api.htm){:target="_blank"}) are both JavaScript libraries that allow you to interact with Tableau, but they do so in two fundamental ways: -* You can use the Embedding JavaScript API for embedding Tableau dashboards in web pages (for example, blog posts), or in line of business applications. +The Extensions API and the Embedding JavaScript API (also known as the [JavaScript API](https://onlinehelp.tableau.com/current/api/js_api/en-us/JavaScriptAPI/js_api.htm){:target="_blank"}) are both JavaScript libraries that allow you to interact with Tableau, but they do so in two fundamental ways: * You can use the Extensions API for integrating web applications into zones in Tableau dashboards. - - +* You can use the Embedding JavaScript API for embedding Tableau dashboards in web pages (for example, blog posts), or in line of business applications. The Extensions API and Embedding JavaScript API share a similar programming model, but there are differences. -| Embedding JavaScript API | Extensions API | +| **Embedding JavaScript API** | **Extensions API** | |------------| ---------------| |Brings Tableau into other web applications | Brings other web applications into Tableau | | Requires embedding Tableau dashboard into a web page | Can be used in Desktop, Server, Online, or embedded dashboard | | Custom-built for each embedded scenario | Can be made as a re-usable, generic-built dashboard component | | Written in JavaScript | Written in JavaScript (similar calls) | - - - diff --git a/docs/trex_sandbox_publish.md b/docs/trex_sandbox_publish.md index b5f604ae..ccb41637 100644 --- a/docs/trex_sandbox_publish.md +++ b/docs/trex_sandbox_publish.md @@ -3,24 +3,18 @@ title: Publish Sandboxed Extensions layout: docs --- -> *\*\* This is preliminary information and is subject to change \*\** - -Sandboxed Extensions are Tableau dashboard extensions that are not permitted to make external network requests. Sandboxed Extensions are hosted by Tableau and run inside an environment that prevents communication with anything except the Tableau hosting server. Sandboxed Extensions are supported in Tableau 2019.4 and later. Available for testing with Tableau 2019.3. +Sandboxed Extensions are Tableau dashboard extensions that are not permitted to make external network requests. Sandboxed Extensions are hosted by Tableau and run inside an environment that prevents communication with anything except the Tableau hosting server. Sandboxed Extensions are supported in Tableau 2019.4 and later. ## Before publishing your extension Be sure to follow the guidelines and requirements to [Create and Test Sandboxed Extensions]({{site.baseurl}}/docs/trex_sandbox_test.html). Make sure your extension works as expected in the development environment. The development environment replicates the Tableau Sandboxed Extension Hosting Cloud Service. If your extension works in the development environment, it will work when you submit the extension package to Tableau for publication. - ## Submit your Sandboxed Extension for publication After you finish developing and testing your Sandboxed Extension, fill out the [Extension Gallery Submission form](https://tabsoft.co/gallerysubmit){:target="_blank"}{:ref="noopener"} with your information and details about your extension. -For information about what goes in the form, see [Submitting your Extension to the Extension Gallery]({{site.baseurl}}/docs/ux_extension_gallery.html){:target="_blank"}. - -Our developers from the Developer Platform team at Tableau will let you know the next steps including legal agreements after you submit your information. If you have any questions about the gallery please send them to [extensiongallery@tableau.com](extensiongallery@tableau.com){:target="_blank"}{:ref="noopener"}. - -Once accepted, Tableau will publish your extension and your extension will be available in the [Extensions Gallery](https://extensiongallery.tableau.com/){:target="_blank"}{:ref="noopener"}. - +For information about what goes in the form, see [Submitting your Extension to the Tableau Exchange]({{site.baseurl}}/docs/ux_extension_gallery.html){:target="_blank"}. +Our developers from the Developer Platform team at Tableau will let you know the next steps including legal agreements after you submit your information. If you have any questions about the Exchange please send them to [extensiongallery@tableau.com](mailto:extensiongallery@tableau.com){:target="_blank"}{:ref="noopener"}. +Once accepted, Tableau will publish your extension and your extension will be available in the [Tableau Exchange](https://exchange.tableau.com/){:target="_blank"}{:ref="noopener"}. diff --git a/docs/trex_sandbox_test.md b/docs/trex_sandbox_test.md index 85404c10..621cf56c 100644 --- a/docs/trex_sandbox_test.md +++ b/docs/trex_sandbox_test.md @@ -6,7 +6,7 @@ layout: docs To provide security for customers, Tableau supports a type of dashboard extension that runs in a sandbox. These Sandboxed Extensions are hosted by Tableau and employ W3C standards, such as Content Security Policy (CSP), to ensure the extension can't make network calls outside of the hosting Tableau Server. This means a Sandboxed Extension can query data in the dashboard using the Extensions API, but it can't send that data anywhere outside of the sandbox. This topic provides information to help you get started creating and testing Sandboxed Extensions. -
    Note If your extension requires resources of outside services, you should not create a Sandboxed Extension. Dashboard Extensions that don't run in the sandbox environment are called Network Enabled Extensions. While Sandboxed Extensions are allowed to run by default on Tableau Server and Tableau Online, Network Enabled Extensions require server and site administrator approval and need to be added to safe list for a site. +
    Note If your extension requires resources or outside services, you should not create a Sandboxed Extension. Dashboard Extensions that don't run in the sandbox environment are called Network Enabled Extensions. While Sandboxed Extensions are allowed to run by default on Tableau Server and Tableau Online, Network Enabled Extensions require server and site administrator approval and need to be added to the safe list for a site.
    **In this section** @@ -22,7 +22,7 @@ Tableau supports two types of dashboard extensions: * **Network Enabled Extensions** - can access resources and applications outside of Tableau. Supported in Tableau 2018.2 and later. -* **Sandboxed Extensions** - run in a Tableau hosted environment and cannot make network calls. Supported in Tableau 2019.4 and later. Available for testing with Tableau 2019.3. +* **Sandboxed Extensions** - run in a Tableau hosted environment and cannot make network calls. Supported in Tableau 2019.4 and later. ## Create Sandboxed Extensions @@ -97,7 +97,6 @@ Before testing your extension in the sandbox, check to make sure that you are on If you have an extension that is ready to test in the sandbox, follow these instructions. - 1. Open the `sandbox-config.json` file. The configuration file has two main entries. The first, specifies the `port` that the sandbox web server will use. You can change this as needed, however, it must match the port you specify in the `.trex` file for your extension. The `sandbox-config.json` file has one entry for the sandboxed version of the UINamespace sample. The file looks like the following: @@ -112,7 +111,6 @@ If you have an extension that is ready to test in the sandbox, follow these inst } } } - ``` 2. Add an new entry under `"extensions"`, for your extension. The syntax for an entry is as follows. @@ -122,15 +120,8 @@ If you have an extension that is ready to test in the sandbox, follow these inst "name": { "path": "relative-or-absolute-path-to-extensions-folder-on-disk" } - - ``` - Replace `name` with the name of your extension. This name is the ID for the extension and becomes part of the URL. The local server for Sandboxed Extensions hosts pages with the following syntax. - - ``` - - http://localhost[:port]/sandbox/[name] - ``` + Replace `name` with the name of your extension. This name is the ID for the extension and becomes part of the URL. The local server for Sandboxed Extensions hosts pages with the following syntax: `http://localhost[:port]/sandbox/[name]`. For example, the default value for port is `8765`. If the name of the extension is `uninamespace`, that name becomes part of the URL that you specify in the `.trex` file: `http://localhost:8765/sandbox/uinamespace/`. Note that in the `.trex` file the full URL also includes the name of the web page in the URL. An implied `index.html` does not work. @@ -150,16 +141,12 @@ If you have an extension that is ready to test in the sandbox, follow these inst "helloworld": { "path": "./mySamples/HelloWorld" } - } } - ``` - 3. Restart the local server (**npm run start-sandbox**). The local Sandboxed Extensions server only reads the configuration file at start up. Anytime you make changes to the `sandbox-config.json` file you need to stop and restart the server. - ### Use the local sandbox path to the extension in the .trex file In the `.trex` file for your extension you need to specify the URL of extension as it will appear on the local sandbox web server. The URL is constructed from several parts. @@ -167,18 +154,14 @@ In the `.trex` file for your extension you need to specify the URL of extension The `` for `` must use the name of local server (`localhost`) and port setting assigned in the `sandboxed-config.json` file (`8765` is the default). This is followed by `sandbox` and the name of your extension, as you specified in the `sandbox-config.json` file. Finally, you specify the name of the HTML page that serves as the home page for your extension. The following example shows the URL for the UINamespace-sandboxed extension. ```xml - - - http://localhost:8765/sandbox/uinamespace/uinamespace.html - - + + http://localhost:8765/sandbox/uinamespace/uinamespace.html + ``` After you update the `.trex` file to point to the sandboxed instance, you can start the local sandbox sever (**npm run start-sandbox**), and then open Tableau and try it out. -For information about making your Sandboxed Extension available to others, see [Publish Sandboxed Extensions]({{site.baseurl}}/docs/trex_sandbox_publish.html). -The local development environment can't be used to deploy or publish your extension. - +For information about making your Sandboxed Extension available to others, see [Publish Sandboxed Extensions]({{site.baseurl}}/docs/trex_sandbox_publish.html). The local development environment can't be used to deploy or publish your extension. ## Troubleshoot the test environment @@ -187,4 +170,3 @@ To troubleshoot issues with your Sandboxed Extension in the test environment, yo Error `Cannot find extension with id: ` If you see this error in the console of your debugging tools, be sure the name (or ID) of the extension in the `sandbox-config.json` file matches the name you specified in the `` in the `.trex` file. - diff --git a/docs/trex_security.md b/docs/trex_security.md index bc0dcc42..975e2855 100644 --- a/docs/trex_security.md +++ b/docs/trex_security.md @@ -30,7 +30,7 @@ When you use HTTPS, all HTTP data is encrypted prior to transmission by the Tran If you plan to make your extension available to others, using HTTPS assures your customers that their data is safe and that they are connecting to a trusted extension. Because the extension is using HTTPS, Tableau is also able to verify the identity of the server that hosts the extension, which prevents various malicious man-in-the-middle attacks that could occur if the extension were to use HTTP alone. -> Note: For development or internal use, you can run your extension on your local computer as `localhost` and you can use the HTTP protocol. See [Use HTTP and localhost for development or internal use](#use-http-and-localhost-for-development-or-internal-use). +| Note: For development or internal use, you can run your extension on your local computer as `localhost` and you can use the HTTP protocol. See [Use HTTP and localhost for development or internal use](#use-http-and-localhost-for-development-or-internal-use). @@ -62,7 +62,6 @@ The `` element in the `.trex` file, looks like the following: SCHEME://SERVER[:PORT][/PATH] - ``` For example, if the extension is hosted on example.com, the entry might look like the following: @@ -71,19 +70,14 @@ For example, if the extension is hosted on example.com, the entry might look lik https://example.com:4043/extension - - ``` Or during development, when you can use `localhost`, the entry might look like the following: ```xml - http://localhost:8080/extension - - ``` At startup, Tableau looks for and validates the extension `.trex` files. If the extension source location does not specify HTTPS or localhost, validation fails and the extension is not registered. These errors are written to the log file. The extension will not load in Tableau. If you examine the log files (for example, with Tableau Log Viewer), you will find something similar to the following: @@ -94,8 +88,6 @@ file: Example.trex Error: Error(11,67): value 'http://example.com/example.html' does not match regular expression facet '[Hh][Tt][Tt][Pp][Ss]://.+|[Hh][Tt][Tt][Pp]://[Ll][Oo][Cc][Aa][Ll][Hh][Oo][Ss][Tt]|[Hh][Tt][Tt][Pp]://[Ll][Oo][Cc][Aa][Ll][Hh][Oo][Ss][Tt][:/].*' (id: C:\Users\\Documents\My Tableau Repository (Beta)\Extensions\example.trex) file: Example.trex - - ``` For more information, see [Use Log files to Troubleshoot Dashboard Extensions]({{site.baseurl}}/docs/trex_logging.html). @@ -116,22 +108,18 @@ For example: - - ``` Or use site-relative or protocol-agnostic links (that is, where the protocol is not specified). ```html - - + - ``` @@ -183,7 +171,7 @@ There are some free and low-cost options that you can use to host your extension you are currently reading!). GitHub Pages makes it really easy to host content, especially if your extension code - is already on GitHub. Check out their tutorial for details: [pages.github.com/](https://pages.github.com) + is already on GitHub. Check out their tutorial for details: [pages.github.com](https://pages.github.com) 2. Host your extension on Heroku. @@ -219,7 +207,7 @@ Information about requesting and creating the TLS/SSL certificates is available - If you have control over your own domain, you can request free certificates from the Certificate Authority [Let's Encrypt](https://letsencrypt.org/){:target="_blank"}. -- You can also request free 90 day TLS/SSL certificates from Comodo, see [Comodo Free SSL](https://ssl.comodo.com/free-ssl-certificate.php?track=8177){:target="_blank"} +- You can also request free 90 day TLS/SSL certificates from Comodo, see [Comodo Free SSL](https://ssl.comodo.com/free-ssl-certificate.php?track=8177){:target="_blank"}. - [Secure your site with HTTPS (Google)](https://support.google.com/webmasters/answer/6073543?hl=en){:target="_blank"}. diff --git a/docs/trex_show_hide.md b/docs/trex_show_hide.md index 3b57f9d5..768972a1 100644 --- a/docs/trex_show_hide.md +++ b/docs/trex_show_hide.md @@ -17,8 +17,6 @@ Starting with Tableau 2019.1, you can use the `ZoneVisibilityType` enum and `set * The object in the dashboard you want to show and hide must be floating (not tiled) - - ## Find the objects and object ids in the dashboard A dashboard contains a group of objects. These objects are worksheets, web pages, UI components like text, vertical or horizontal layout containers, or blank zones for spacing. To be able to show or hide an object in the dashboard, you need to have information to identify the object. Starting with the `tableau-extensions-1.1.0.js` library, objects in the dashboard have properties for `name`, `id`, and `isVisible`. @@ -33,11 +31,9 @@ For example, a worksheet in a dashboard fits inside a layout zone. To be able to The following code example iterates through the objects in the dashboard and prints out information to the console. ```js - - tableau.extensions.dashboardContent.dashboard.objects.forEach(function(object){ - console.log(object.name + ":" + object.type + ":" + object.id + ":" + object.isVisible); - }); - +tableau.extensions.dashboardContent.dashboard.objects.forEach(function(object){ + console.log(object.name + ":" + object.type + ":" + object.id + ":" + object.isVisible); +}); ``` ## Create a map of the zone and its show or hide state @@ -53,39 +49,32 @@ In this example, the zones Wiki and ShowHide have their properties set to hide. ShowHide is the zone that contains the dashboard extension. The example creates two `zoneVisibilityMap` objects: `extensionVisibilityObject` and `wikiVisibilityObject`. The Wiki zone is also added to the `extensionVisibilityObject`, where it can be passed to the `setZoneVisibilityAsync` method when the dashboard extension is first hidden. You can toggle the visibility of multiple zones in a `zoneVisibilityMap`. ```javascript - - let wikiZone = ["Wiki"]; - let extensionName = ["ShowHide"]; - let extensionVisibilityObject = {}; - let wikiVisibilityObject = {}; - - tableau.extensions.dashboardContent.dashboard.objects.forEach(function(object){ - if(extensionName.includes(object.name)){ - extensionVisibilityObject[object.id] = tableau.ZoneVisibilityType.Hide; - }else if(wikiZone.includes(object.name)){ - wikiVisibilityObject[object.id] = tableau.ZoneVisibilityType.Hide; - extensionVisibilityObject[object.id] = tableau.ZoneVisibilityType.Hide; - } - }); - +let wikiZone = ["Wiki"]; +let extensionName = ["ShowHide"]; +let extensionVisibilityObject = {}; +let wikiVisibilityObject = {}; + +tableau.extensions.dashboardContent.dashboard.objects.forEach(function(object){ + if(extensionName.includes(object.name)){ + extensionVisibilityObject[object.id] = tableau.ZoneVisibilityType.Hide; + }else if(wikiZone.includes(object.name)){ + wikiVisibilityObject[object.id] = tableau.ZoneVisibilityType.Hide; + extensionVisibilityObject[object.id] = tableau.ZoneVisibilityType.Hide; + } +}); ``` - ## Set the visibility of the zone in the dashboard After you have built the map of zone id and the zone's show or hide state, you can call the `setZoneVisibilityAsync` method and pass it the zone visibility map you created. The following code example, hides the zone that contains the dashboard extension (`ShowHide`) and the zone (`Wiki`) that is used to contain the wiki page and the City Map worksheet, and then prints a message to the console. - ```javascript - - tableau.extensions.dashboardContent.dashboard.setZoneVisibilityAsync(extensionVisibilityObject).then(() => { - console.log("done"); - }) - +tableau.extensions.dashboardContent.dashboard.setZoneVisibilityAsync(extensionVisibilityObject).then(() => { + console.log("done"); +}) ``` - ## Troubleshooting and debugging show and hide So you have hidden your extension, great! So how do you access the shortcut menu so that you can reload the extension while you are developing and testing your extension? It might not be obvious, but you can access the shortcut menu in the Layout pane in the dashboard, under **Item Hierarchy**. If you right click the extension, you have access to the shortcut menu. @@ -97,57 +86,51 @@ If you want to use the Debug Option, **Pause Before Loading**, you should make s The following code shows how an extension can be used to create a tool-tip like dialog box, by showing and hiding zones in a dashboard. This example uses the Superstore sample as a starting point. The dashboard has actions to call the wikipedia page for the state selected and an action to filter the City Map based on the state selected. This example assumes that there is a zone called `Wiki` that contains the City Map worksheet and a web page (wikipedia.org). The example also hides the extension itself (`ShowHide`) and then sets an event listener on a `MarkSelectionChanged` event in the State Map worksheet. An event occurs when a user clicks a state in the map. If a single state is selected, the event handler method sets the zone visibility and calls `setZoneVisibilityAsync` to show the zone with the city map and wikipedia page for the state. -```js - - tableau.extensions.initializeAsync().then(function() { - tableau.extensions.dashboardContent.dashboard.objects.forEach(function(object){ - console.log(object.name + ":" + object.type + ":" + object.id + ":" + object.isVisible); - }); - - let wikiZone = ["Wiki"]; - let extensionName = ["ShoWHide"]; - let extensionVisibilityObject = {}; - let wikiVisibilityObject = {}; - - tableau.extensions.dashboardContent.dashboard.objects.forEach(function(object){ - if(extensionName.includes(object.name)){ - extensionVisibilityObject[object.id] = tableau.ZoneVisibilityType.Hide; - }else if(wikiZone.includes(object.name)){ - wikiVisibilityObject[object.id] = tableau.ZoneVisibilityType.Hide; - extensionVisibilityObject[object.id] = tableau.ZoneVisibilityType.Hide; - } - }); - - tableau.extensions.dashboardContent.dashboard.setZoneVisibilityAsync(extensionVisibilityObject).then(() => { - console.log("done"); - }).then(()=>{ - worksheet = tableau.extensions.dashboardContent.dashboard.worksheets.find(ws => ws.name === "State Map"); - worksheet.addEventListener(tableau.TableauEventType.MarkSelectionChanged, selection) - }) - - function selection(data) { - data.getMarksAsync().then(marks => { - if (marks.data[0].data.length === 1) { - toggleWikiVisibility(tableau.ZoneVisibilityType.Show); - } else { - toggleWikiVisibility(tableau.ZoneVisibilityType.Hide); - } - }) - } - - function toggleWikiVisibility(visibility) { - for(let key in wikiVisibilityObject) { - wikiVisibilityObject[key] = visibility; - } - tableau.extensions.dashboardContent.dashboard.setZoneVisibilityAsync(wikiVisibilityObject).then(() => { - console.log("done"); - }); - } - +```javascript +tableau.extensions.initializeAsync().then(function() { + tableau.extensions.dashboardContent.dashboard.objects.forEach(function(object){ + console.log(object.name + ":" + object.type + ":" + object.id + ":" + object.isVisible); }); - - - - -``` \ No newline at end of file + let wikiZone = ["Wiki"]; + let extensionName = ["ShoWHide"]; + let extensionVisibilityObject = {}; + let wikiVisibilityObject = {}; + + tableau.extensions.dashboardContent.dashboard.objects.forEach(function(object){ + if(extensionName.includes(object.name)){ + extensionVisibilityObject[object.id] = tableau.ZoneVisibilityType.Hide; + }else if(wikiZone.includes(object.name)){ + wikiVisibilityObject[object.id] = tableau.ZoneVisibilityType.Hide; + extensionVisibilityObject[object.id] = tableau.ZoneVisibilityType.Hide; + } + }); + + tableau.extensions.dashboardContent.dashboard.setZoneVisibilityAsync(extensionVisibilityObject).then(() => { + console.log("done"); + }).then(()=>{ + worksheet = tableau.extensions.dashboardContent.dashboard.worksheets.find(ws => ws.name === "State Map"); + worksheet.addEventListener(tableau.TableauEventType.MarkSelectionChanged, selection) + }) + + function selection(data) { + data.getMarksAsync().then(marks => { + if (marks.data[0].data.length === 1) { + toggleWikiVisibility(tableau.ZoneVisibilityType.Show); + } else { + toggleWikiVisibility(tableau.ZoneVisibilityType.Hide); + } + }) +} + +function toggleWikiVisibility(visibility) { + for(let key in wikiVisibilityObject) { + wikiVisibilityObject[key] = visibility; + } + tableau.extensions.dashboardContent.dashboard.setZoneVisibilityAsync(wikiVisibilityObject).then(() => { + console.log("done"); + }); +} + +}); +``` diff --git a/docs/trex_tableau_viz.md b/docs/trex_tableau_viz.md index 8ffae77a..491fcd7d 100644 --- a/docs/trex_tableau_viz.md +++ b/docs/trex_tableau_viz.md @@ -3,7 +3,7 @@ title: Add Tableau Viz to your Dashboard Extensions layout: docs --- -Tableau Viz provides a lightweight method for creating visualizations in Tableau. You provide a declarative description of graph or chart, and then call a method to render the description as an SVG image that you can embed in your dashboard extension. The description includes the data (or programmatically adds the data) and specifies the type of chart you wish to create and how it should be encoded. This feature is available through the Dashboard Extensions API and employs the same visualization pipeline that Tableau uses. +Tableau Viz provides a lightweight method for creating visualizations in Tableau. You provide a declarative description of a graph or chart, and then call a method to render the description as an SVG image that you can embed in your dashboard extension. The description includes the data (or programmatically adds the data) and specifies the type of chart you wish to create and how it should be encoded. This feature is available through the Dashboard Extensions API and employs the same visualization pipeline that Tableau uses. @@ -46,7 +46,7 @@ graph LR A Tableau Viz is defined by a specification. This is the `inputSpec` that you pass as an argument to the `createVizImageAsync` method. The `inputSpec` is a JavaScript object that contains the embedded data and visual specification details. There are two main parts to the `inputSpec`: -* the `data:` (an array of objects, for example, the selected measures and dimensions in the dashboard) +* the data (an array of objects, for example, the selected measures and dimensions in the dashboard) * information about how to format that data (size of viz, mark type, mark color, encoding) @@ -54,32 +54,30 @@ The `inputSpec` is a structured JavaScript object. The following example shows a ```javascript - - var yourEmbeddedDataSpec = { - description: 'A simple chart with embedded data.', - data: { - values: [ - { Category: 'A', Sales: 28 }, - { Category: 'B', Sales: 55 }, - { Category: 'C', Sales: 43 }, - { Category: 'D', Sales: 91 }, - { Category: 'E', Sales: 81 }, - { Category: 'F', Sales: 53 }, - { Category: 'G', Sales: 19 }, - { Category: 'H', Sales: 87 }, - { Category: 'I', Sales: 52 } - ] - }, - mark: tableau.MarkType.Bar, - encoding: { - columns: { field: 'Category', type: tableau.VizImageEncodingType.Discrete }, - rows: { field: 'Sales', type: tableau.VizImageEncodingType.Continuous, hidden: true}, - color: { field: 'Sales', type: tableau.VizImageEncodingType.Continuous, palette: 'tableau-map-temperatur'}, - text: { field: 'Category', type: tableau.VizImageEncodingType.Discrete }, - size: { field: 'Category', type: tableau.VizImageEncodingType.Discrete} - } - }; - +var yourEmbeddedDataSpec = { + description: 'A simple chart with embedded data.', + data: { + values: [ + { Category: 'A', Sales: 28 }, + { Category: 'B', Sales: 55 }, + { Category: 'C', Sales: 43 }, + { Category: 'D', Sales: 91 }, + { Category: 'E', Sales: 81 }, + { Category: 'F', Sales: 53 }, + { Category: 'G', Sales: 19 }, + { Category: 'H', Sales: 87 }, + { Category: 'I', Sales: 52 } + ] + }, + mark: tableau.MarkType.Bar, + encoding: { + columns: { field: 'Category', type: tableau.VizImageEncodingType.Discrete }, + rows: { field: 'Sales', type: tableau.VizImageEncodingType.Continuous, hidden: true}, + color: { field: 'Sales', type: tableau.VizImageEncodingType.Continuous, palette: 'tableau-map-temperatur'}, + text: { field: 'Category', type: tableau.VizImageEncodingType.Discrete }, + size: { field: 'Category', type: tableau.VizImageEncodingType.Discrete} + } +}; ``` For more information about the `inputSpec`, see [Tableau Viz Reference]({{site.baseurl}}/docs/trex_tableau_viz_ref.html). @@ -90,12 +88,11 @@ For more information about the `inputSpec`, see [Tableau Viz Reference]({{site.b After you create the `inputSpec` you pass it as an argument to the `createVizImageAsync` method. The method returns an SVG image that can be used by the extension. This example takes the `yourEmbeddedDataSpec` that was defined in the previous step, and uses that to describe the chart to create. - ```javascript - tableau.extensions.createVizImageAsync(yourEmbeddedDataSpec).then((svg) => { - ... - }); - - ``` +```javascript +tableau.extensions.createVizImageAsync(yourEmbeddedDataSpec).then((svg) => { + ... +}); +``` ## Display the SVG image in the dashboard extension @@ -103,20 +100,19 @@ After you create the `inputSpec` you pass it as an argument to the `createVizIma The asynchronous method returns an SVG image as the promise. Here is one way of taking that SVG and embedding it as a an element in your extension web page. In this example, the `svg` is converted to a JavaScript `Blob`, and the `Blob` is used as the image data source in the hosting dashboard extensions page. ```javascript - tableau.extensions.createVizImageAsync(yourEmbeddedDataSpec).then((svg) => { - console.log(svg); - var blob = new Blob([svg], { type: 'image/svg+xml' }); - var url = URL.createObjectURL(blob); - var image = document.createElement('img'); - image.src = url; - image.style.maxWidth = '100%'; - var vizApiElement = document.getElementById('viz-container'); - vizApiElement.appendChild(image); - image.addEventListener('load', function () { return URL.revokeObjectURL(url); }, { once: true }); - }, (err) => { - console.log(err); - }); - +tableau.extensions.createVizImageAsync(yourEmbeddedDataSpec).then((svg) => { + console.log(svg); + var blob = new Blob([svg], { type: 'image/svg+xml' }); + var url = URL.createObjectURL(blob); + var image = document.createElement('img'); + image.src = url; + image.style.maxWidth = '100%'; + var vizApiElement = document.getElementById('viz-container'); + vizApiElement.appendChild(image); + image.addEventListener('load', function () { return URL.revokeObjectURL(url); }, { once: true }); +}, (err) => { + console.log(err); +}); ``` Tableau renders an image that looks something like this: diff --git a/docs/trex_tableau_viz_ref.md b/docs/trex_tableau_viz_ref.md index 865edc4a..fdeb3366 100644 --- a/docs/trex_tableau_viz_ref.md +++ b/docs/trex_tableau_viz_ref.md @@ -18,9 +18,7 @@ The following section describes the components and syntax of the `inputSpec`. Fo The `createVizImageAsync` method is one of the methods in the Tableau Dashboard Extensions API `extensions` namespace. The method has the following syntax: ```javascript - createVizImageAsync( inputSpec: *object* ): Promise - ``` This method takes a single argument, the `inputSpec`, a JavaScript object, and returns the SVG description of that image. To call this method, you first initialize the Dashboard Extensions API (`tableau.extensions.initialize()`). You then create the `inputSpec` object that defines your graphic. @@ -34,8 +32,6 @@ The `inputSpec` is a JavaScript object that specifies the name-value pairs to us The following shows an example `inputSpec` that creates a bar chart image. ```javascript - - { description: "A bar chart with multiple encodings", size: {width: 800, height: 600}, @@ -57,12 +53,10 @@ The following shows an example `inputSpec` that creates a bar chart image. text: {field: "Category", type: tableau.VizImageEncodingType.Discrete} } } - - ``` --- -## Descripion of `inputSpec` properties +## Description of `inputSpec` properties The following table describes the properties in the `inputSpec`, the JavaScript object that you provide as input to the `createVizImageAsync` method. @@ -77,7 +71,6 @@ The following table describes the properties in the `inputSpec`, the JavaScript ```javascript title: "My Custom Viz", - ``` ### `data` @@ -98,7 +91,6 @@ data: { { Category: 'I', Sales: 52 } ] }, - ``` ### `mark` @@ -112,7 +104,6 @@ Specifies a mark color for all marks, for example, hex values. This is equivalen ```javascript markcolor: "#FFA500", - ``` ### `size` @@ -129,7 +120,6 @@ If you specify the size, you must specify both the width and height. If you don' ```javascript size: {width: 800, height: 600}, - ``` ### `encoding` @@ -153,12 +143,10 @@ Within these properties, you must specify the field to encode and its type (`tab The following are examples of how you might specify the encodings for columns and rows: ```javascript - encoding: { columns: {field: "Sales", type: tableau.VizImageEncodingType.Continuous, title: "My Custom Title", showtitle: false}, rows: {field: "Category", type: tableau.VizImageEncodingType.Discrete } } - ``` ```javascript @@ -190,7 +178,6 @@ Specifies the size encoding of the mark. The `size` property corresponds to the Example of fixed sized type: ```javascript - encoding: { ... size: {field: "Age", setting: tableau.VizImageSizeSettingType.Fixed, alignment: tableau.VizImageSizeSettingAlignmentType.Right, width_in_axis_units: 3} @@ -217,9 +204,6 @@ Specifies the sort order for a field (continuous or discrete). Supports sorting ``` - - - #### encoding: `color` The `color` property corresponds to the Color button on the Marks card. The color can contain additional properties: @@ -238,22 +222,17 @@ You can specify one of the following Tableau color palettes with the `palette` p The following is an example that shows how you might encode a continuous field with a Tableau palette. You can also create custom color palettes for continuous fields. See [Create Custom Color Palettes](#create-custom-color-palettes). ```javascript - encoding: { ... color: { field: 'Measure', type: tableau.VizImageEncodingType.Continuous, palette: 'green_blue_white_diverging_10_0'}, ... } - ``` - | Continuous colors palettes | Palette name | |:--- |:--- | | ![Tableau Continuous Palette]({{site.baseurl}}/assets/continuous_palette.png) | `blue_10_0`
    `orange_10_0`
    `green_10_0`
    `red_10_0`
    `purple_10_0`
    `brown_10_0`
    `gray_10_0`
    `gray_warm_10_0`
    `blue_teal_10_0`
    `orange_gold_10_0`
    `green_gold_10_0`
    `red_gold_10_0`
    `orange_blue_diverging_10_0`
    `red_green_diverging_10_0`
    `green_blue_diverging_10_0`
    `red_blue_diverging_10_0`
    `red_black_10_0`
    `gold_purple_diverging_10_0`
    `red_green_gold_diverging_10_0`
    `sunrise_sunset_diverging_10_0`
    `orange_blue_white_diverging_10_0`
    `red_green_white_diverging_10_0`
    `green_blue_white_diverging_10_0`
    `red_blue_white_diverging_10_0`
    `red_black_white_diverging_10_0`
    `tableau-blue-light`
    `tableau-orange-light`
    `tableau-orange-blue-light`
    `tableau-map-blue-green`
    `tableau-map-temperatur` | - - **`palette` names for discrete fields** You can specify one of the following Tableau color palettes with the `palette` property for discrete fields. Note that the list of available palettes depends upon the version of Tableau that is being used. Be aware that the palette colors are subject to change. @@ -266,7 +245,6 @@ encoding: { color: { field: 'Category', type: tableau.VizImageEncodingType.Discrete, palette: 'seattle_grays_10_0'}, ... } - ``` | Discrete color palettes | Palette name | @@ -276,7 +254,6 @@ encoding: { --- - #### Create custom color palettes You can set the color palette to a custom diverging or custom sequential color palette that you specify, and not just the Tableau defined palates, such as, `green_blue_white_diverging_10_0`. @@ -287,20 +264,14 @@ You can set the color palette to a custom diverging or custom sequential color p |`tableau.VizImagePaletteType.CustomDiverging` | Defines a custom diverging palette. Specify the `start` value and an `end` value, each as a hexadecimal value. | | `tableau.VizImagePaletteType.CustomSequential` | Defines a custom sequential palette. Specify the `end` value as a hexadecimal value. | - For example, you could set a custom palette as shown in the following examples: - - ```javascript - - palette: tableau.VizImagePaletteType.CustomDiverging, start: "#FFB6C1", end: "#90ee90" - - ``` +```javascript +palette: tableau.VizImagePaletteType.CustomDiverging, start: "#FFB6C1", end: "#90ee90" +``` Or - ```javascript - - palette: tableau.VizImagePaletteType.CustomSequential, end: "#FFB6C1" - - ``` \ No newline at end of file +```javascript +palette: tableau.VizImagePaletteType.CustomSequential, end: "#FFB6C1" +``` diff --git a/docs/trex_typescript.md b/docs/trex_typescript.md index 892fc1a3..22062df4 100644 --- a/docs/trex_typescript.md +++ b/docs/trex_typescript.md @@ -10,7 +10,7 @@ The Extensions API is a JavaScript library. If you author in TypeScript, Tableau - TOC {:toc} -
    Note If you want to examine and use TypeScript versions of several of the sample extensions in the Samples folder, see Samples-Typescript (GitHub) and follow the instructions to Use the TypeScript Samples. +
    Note If you want to examine and use TypeScript versions of several of the sample extensions in the Samples folder, see Samples-Typescript (GitHub) and follow the instructions to Use the TypeScript Samples.
    ## Install the Tableau Extensions API TypeScript types @@ -100,4 +100,4 @@ In the HTML code for the extensions, the JavaScript files are referenced. The fo - [TypeScript in Visual Studio Code](https://code.visualstudio.com/docs/languages/typescript?=target="_blank") -- [TypeScript Sample Extensions (GitHub)](https://github.com/tableau/extensions-api/tree/master/Samples-TypeScript) and [Use the TypeScript samples]({{site.baseurl}}/docs/trex_examples.html#use-the-typescript-samples) +- [TypeScript Sample Extensions (GitHub)](https://github.com/tableau/extensions-api/tree/main/Samples-TypeScript) and [Use the TypeScript samples]({{site.baseurl}}/docs/trex_examples.html#use-the-typescript-samples) diff --git a/docs/trex_xss_guidance.md b/docs/trex_xss_guidance.md index bb649881..1a168c83 100644 --- a/docs/trex_xss_guidance.md +++ b/docs/trex_xss_guidance.md @@ -34,7 +34,7 @@ If your dashboard extension accepts text input from users through forms or text Do not use or allow JavaScript code within the ` + ``` Only allow or use references to JavaScript files within the script tags. ``` @@ -49,7 +49,6 @@ If your dashboard extension accepts text input from users through forms or text // Link to libraries on the local host: - ``` -For more information, see [https://github.com/tableau/extensions-api/issues/103](https://github.com/tableau/extensions-api/issues/103){:target="_blank"} +For more information, see [https://github.com/tableau/extensions-api/issues/103](https://github.com/tableau/extensions-api/issues/103){:target="_blank"}. diff --git a/docs/ux_design.md b/docs/ux_design.md index 008b13f2..02413b9a 100644 --- a/docs/ux_design.md +++ b/docs/ux_design.md @@ -44,12 +44,10 @@ These guidelines cover the main things you need to know about designing a great ### Deploying your Extension | ---------| ------- | -|[Submitting your Extension to the Extension Gallery]({{site.baseurl}}/docs/ux_extension_gallery.html) | How to style your extension in accordance with the Tableau brand and your personal/company brand.| +|[Submitting your Extension to the Tableau Exchange]({{site.baseurl}}/docs/ux_extension_gallery.html) | How to style your extension in accordance with the Tableau brand and your personal/company brand.| ---   ![Extensions are made using a manifest file called a .trex! FreLard stands for the Seattle neighborhoods of Fremont and Wallingford, where Tableau's headquarters stands.](imgs/trex.png) - ->*This document is a work-in-progress. To give feedback, ask questions, or if you have technical questions about extensions, contact [devplat@tableau.com](mailto:devplat@tableau.com).* \ No newline at end of file diff --git a/docs/ux_extension_gallery.md b/docs/ux_extension_gallery.md index d76e1928..9a0386dd 100644 --- a/docs/ux_extension_gallery.md +++ b/docs/ux_extension_gallery.md @@ -20,8 +20,6 @@ You may be interested in sharing your extension for others to download and use i **[How to Submit your Extension](#how-to-submit-your-extension)** -  - --- ## Tableau Exchange Card Example @@ -36,8 +34,6 @@ This is what an extension looks like to a user while browsing the Tableau Exchan | **Tagline** | The tagline is one sentence that explains what the extension does. The maximum length is 96 characters. This tagline is also used within the extension configuration dialog. Learn more at [Extension Components and Modes]({{site.baseurl}}/docs/Interaction_Guidelines/ux_components_modes.html).| -  - ## Exchange Page Example Users reach pages like this when they want to know more about a particular extension. @@ -49,8 +45,6 @@ Users reach pages like this when they want to know more about a particular exten | **Developer Info** | Take credit for your work. Gather links, files, and/or contact info for the following items:
    **Policy**: Privacy Policy (website link or PDF)
    **Usage**: Terms of Service (website link or PDF), and terms of service
    **Support**: Personal or company website, FAQ, PDF, and contact info for feedback and inquires
    **Version**: Current version of your extension. | | **Featured Images** | You can upload one to three images of your extension in action. Dimensions for the screenshots must be 1200x680 pixels and uploaded as `.png` files. Take caution that screenshots do not reveal any sensitive or confidential data. | -  - ## How to Submit your Extension -After completing your extension, fill out the [Tableau Exchange Submission form](https://tabsoft.co/gallerysubmit){:target="_blank"}{:ref="noopener"} with your information and extension details. The extension name in the template needs to match the name you specified for your extension in the manifest file (`.trex`). The 280x280 pixel `.png` icon that you attach with your submission must look like the icon you included in your manifest file (they just have different dimensions). Our developers from the Developer Platform team at Tableau will let you know the next steps including legal agreements after you submit. If you have any questions about the Tableau Exchange please send them to [extensiongallery@tableau.com](extensiongallery@tableau.com){:target="_blank"}{:ref="noopener"}. +After completing your extension, fill out the [Tableau Exchange Submission form](https://tabsoft.co/gallerysubmit){:target="_blank"}{:ref="noopener"} with your information and extension details. The extension name in the template needs to match the name you specified for your extension in the manifest file (`.trex`). The 280x280 pixel `.png` icon that you attach with your submission must look like the icon you included in your manifest file (they just have different dimensions). Our developers from the Developer Platform team at Tableau will let you know the next steps including legal agreements after you submit. If you have any questions about the Tableau Exchange please send them to [extensiongallery@tableau.com](mailto:extensiongallery@tableau.com){:target="_blank"}{:ref="noopener"}.