├── .gitattributes ├── .gitignore ├── DataDrivenParameters_2.latest.trex ├── LICENSE ├── README.md ├── docs ├── 2.0.0 │ ├── asset-manifest.json │ ├── favicon.ico │ ├── index.html │ ├── manifest.json │ ├── precache-manifest.dc7e0c72d8caeec99a4b170eb6b8ad0f.js │ ├── service-worker.js │ ├── static │ │ ├── css │ │ │ ├── main.a0b18684.chunk.css │ │ │ └── main.a0b18684.chunk.css.map │ │ └── js │ │ │ ├── 2.6e32bc5d.chunk.js │ │ │ ├── 2.6e32bc5d.chunk.js.map │ │ │ ├── main.8c9ad036.chunk.js │ │ │ ├── main.8c9ad036.chunk.js.map │ │ │ ├── runtime~main.717e2416.js │ │ │ └── runtime~main.717e2416.js.map │ └── tableau.extensions.1.latest.js ├── 2.1.0 │ ├── asset-manifest.json │ ├── favicon.ico │ ├── index.html │ ├── manifest.json │ ├── precache-manifest.03cf0849ed10715b922211b8056357c4.js │ ├── service-worker.js │ ├── static │ │ ├── css │ │ │ ├── main.673a05ca.chunk.css │ │ │ └── main.673a05ca.chunk.css.map │ │ └── js │ │ │ ├── 2.51c5d46f.chunk.js │ │ │ ├── 2.51c5d46f.chunk.js.map │ │ │ ├── main.bb588e6f.chunk.js │ │ │ ├── main.bb588e6f.chunk.js.map │ │ │ ├── runtime~main.0d9ba244.js │ │ │ └── runtime~main.0d9ba244.js.map │ └── tableau.extensions.1.latest.js ├── 2.latest │ ├── asset-manifest.json │ ├── favicon.ico │ ├── index.html │ ├── manifest.json │ ├── precache-manifest.d75aafc2866f2a41c3713ec81c2e13c8.js │ ├── service-worker.js │ ├── static │ │ ├── css │ │ │ ├── main.673a05ca.chunk.css │ │ │ └── main.673a05ca.chunk.css.map │ │ └── js │ │ │ ├── 2.51c5d46f.chunk.js │ │ │ ├── 2.51c5d46f.chunk.js.map │ │ │ ├── main.3aea75ac.chunk.js │ │ │ ├── main.3aea75ac.chunk.js.map │ │ │ ├── runtime~main.e725b044.js │ │ │ └── runtime~main.e725b044.js.map │ └── tableau.extensions.1.latest.js ├── asset-manifest.json ├── favicon.ico ├── index.html ├── manifest.json ├── precache-manifest.8f5c5c66632ab1c8eb2b9ab4c458256a.js ├── service-worker.js ├── static │ ├── css │ │ ├── main.cb967471.chunk.css │ │ └── main.cb967471.chunk.css.map │ └── js │ │ ├── 2.bbca4fae.chunk.js │ │ ├── 2.bbca4fae.chunk.js.map │ │ ├── main.ae08df8d.chunk.js │ │ ├── main.ae08df8d.chunk.js.map │ │ ├── runtime~main.01d56cb3.js │ │ └── runtime~main.01d56cb3.js.map └── tableau.extensions.1.latest.js ├── package.json ├── public ├── favicon.ico ├── index.html ├── manifest.json └── tableau.extensions.1.latest.js ├── sandboxed ├── DataDrivenParameters_Sandboxed.trex ├── DataDrivenParameters_Sandboxed_Test.trex ├── config-overrides.js ├── config.json ├── package.json ├── public │ ├── config.html │ ├── favicon.ico │ ├── index.html │ ├── manifest.json │ └── tableau.extensions.1.latest.min.js ├── src │ ├── Configure.tsx │ ├── DataDrivenParameter.tsx │ ├── Selected.tsx │ ├── Selector.tsx │ ├── Setting.tsx │ ├── entry_config.tsx │ ├── entry_index.tsx │ ├── imgs │ │ └── arrow.png │ ├── index.tsx │ ├── react-app-env.d.ts │ ├── serviceWorker.ts │ └── style.css ├── tsconfig.json └── yarn.lock ├── src ├── Configure.tsx ├── DataDrivenParameter.tsx ├── Home.tsx ├── Selected.tsx ├── Selector.tsx ├── Setting.tsx ├── home.css ├── imgs │ └── arrow.png ├── index.tsx ├── react-app-env.d.ts ├── serviceWorker.ts └── style.css ├── tsconfig.json └── yarn.lock /.gitattributes: -------------------------------------------------------------------------------- 1 | /docs/* linguist-generated -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /sandboxed/node_modules 6 | /.pnp 7 | .pnp.js 8 | 9 | # testing 10 | /coverage 11 | 12 | # production 13 | /build 14 | /sandboxed/build 15 | 16 | # misc 17 | .DS_Store 18 | .env.local 19 | .env.development.local 20 | .env.test.local 21 | .env.production.local 22 | 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | -------------------------------------------------------------------------------- /DataDrivenParameters_2.latest.trex: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | en_US 5 | 6 | Automatically update your parameters based on your data! 7 | 8 | 0.9 9 | 10 | https://tableau.github.io/extension-data-driven-parameters/2.latest/#/parameter 11 | 12 | iVBORw0KGgoAAAANSUhEUgAAAEYAAABGCAYAAABxLuKEAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFHGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDE5LTAyLTA2VDE0OjE4OjQ5LTA4OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAxOS0wMi0wNlQxNDoxOToxNS0wODowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAxOS0wMi0wNlQxNDoxOToxNS0wODowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo3ZjJhNDI0YS02YzY2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 13 | 14 | 15 | 16 | 17 | 18 | 19 | Data-Driven Parameter 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Tableau 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![As-Is](https://img.shields.io/badge/Support%20Level-As--Is-e8762c.svg)](https://www.tableau.com/support-levels-it-and-developer-tools) 2 | 3 | # Data-Driven Parameters 4 | This extension allows you to add a parameter to a Tableau dashboard whose domain is based on your data. Added a new product line? Expanding to new regions? No longer do you need to manually edit the parameter to update it, with this extension your parameter values update automatically! 5 | 6 | ## Using the Extension from Tableau Exchange (Recommended) 7 | See the Tableau Help topic [Use Dashboard Extensions](https://help.tableau.com/current/pro/desktop/en-us/dashboard_extensions.htm) for directions. When presented with the list of available Dashboard Extensions, search for Data Driven Parameters to find and install this one. 8 | 9 | ### Using the Extension 10 | 1. Create a parameter that accepts all values (no lists or ranges), make sure it has a data type matching the field you want to use to populate it. 11 | 2. Drag in a new Extension object to your dashboard and click "My Extensions" 12 | 3. Find the manifest (.trex) file you downloaded above. 13 | 4. In the pop-up configuration window select the parameter you created above for the extension to manipulate. 14 | 5. Select the worksheet that holds the field you want to base your parameter on. 15 | 6. Select the field you want to base your parameter on. 16 | 7. Optional: Configure the options and formatting settings. 17 | 8. Click 'OK'. 18 | 19 | ## Download the Extension Code to Develop Locally 20 | If you want to use a locally-built version of this extension or if you want to make any of your own changes, follow these steps: 21 | 22 | 1. Make sure you have [Node.js](https://nodejs.org) and [Yarn](https://yarnpkg.com) installed. 23 | 2. Clone or download and unzip this repository. Open the command line to the `extension-data-driven-parameters-master` folder and run `yarn` to install the node modules. 24 | 3. Edit the `homepage` in the `package.json` file to the server where you are going to host the extension. For example: 25 | ``` 26 | "homepage": "http://localhost:8080", 27 | ``` 28 | 4. In the command line run `yarn build` to build the extension with the new homepage. 29 | 5. Copy the files in `build` to your web server at the path you specified in Step 3. 30 | 6. Update the existing or create a new manifest file (.trex) to point to the URL where you are hosting the extension with `/#/parameter` at the end. For example: `http://localhost:8080/#/parameter`. 31 | 32 | ## Support 33 | Tableau customers can contact the Tableau Support team for help. 34 | 35 | For any local build or code related questions, please post to the [Issues](https://github.com/tableau/extension-data-driven-parameters/issues) tab here for community support. 36 | 37 | ### Mac Desktop 2018.3 and lower 38 | Note: Please use arrow keys and 'Enter' to select dropdown options. 39 | -------------------------------------------------------------------------------- /docs/2.0.0/asset-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "files": { 3 | "main.css": "/extension-data-driven-parameters/2.0.0/static/css/main.a0b18684.chunk.css", 4 | "main.js": "/extension-data-driven-parameters/2.0.0/static/js/main.8c9ad036.chunk.js", 5 | "main.js.map": "/extension-data-driven-parameters/2.0.0/static/js/main.8c9ad036.chunk.js.map", 6 | "runtime~main.js": "/extension-data-driven-parameters/2.0.0/static/js/runtime~main.717e2416.js", 7 | "runtime~main.js.map": "/extension-data-driven-parameters/2.0.0/static/js/runtime~main.717e2416.js.map", 8 | "static/js/2.6e32bc5d.chunk.js": "/extension-data-driven-parameters/2.0.0/static/js/2.6e32bc5d.chunk.js", 9 | "static/js/2.6e32bc5d.chunk.js.map": "/extension-data-driven-parameters/2.0.0/static/js/2.6e32bc5d.chunk.js.map", 10 | "index.html": "/extension-data-driven-parameters/2.0.0/index.html", 11 | "precache-manifest.dc7e0c72d8caeec99a4b170eb6b8ad0f.js": "/extension-data-driven-parameters/2.0.0/precache-manifest.dc7e0c72d8caeec99a4b170eb6b8ad0f.js", 12 | "service-worker.js": "/extension-data-driven-parameters/2.0.0/service-worker.js", 13 | "static/css/main.a0b18684.chunk.css.map": "/extension-data-driven-parameters/2.0.0/static/css/main.a0b18684.chunk.css.map" 14 | } 15 | } -------------------------------------------------------------------------------- /docs/2.0.0/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tableau/extension-data-driven-parameters/3a97c522fb3cf36bd389366ef7626066f679345f/docs/2.0.0/favicon.ico -------------------------------------------------------------------------------- /docs/2.0.0/index.html: -------------------------------------------------------------------------------- 1 | Data-Driven Parameters Extension
-------------------------------------------------------------------------------- /docs/2.0.0/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Data-Driven Parameters", 3 | "name": "Data-Driven Parameters", 4 | "icons": [{ 5 | "src": "favicon.ico", 6 | "sizes": "64x64 32x32 24x24 16x16", 7 | "type": "image/x-icon" 8 | }], 9 | "start_url": ".", 10 | "display": "standalone", 11 | "theme_color": "#000000", 12 | "background_color": "#ffffff" 13 | } -------------------------------------------------------------------------------- /docs/2.0.0/precache-manifest.dc7e0c72d8caeec99a4b170eb6b8ad0f.js: -------------------------------------------------------------------------------- 1 | self.__precacheManifest = (self.__precacheManifest || []).concat([ 2 | { 3 | "revision": "68867bb1532e4dba9258b6aad5151ac6", 4 | "url": "/extension-data-driven-parameters/2.0.0/index.html" 5 | }, 6 | { 7 | "revision": "f91160f4b9f466811a79", 8 | "url": "/extension-data-driven-parameters/2.0.0/static/css/main.a0b18684.chunk.css" 9 | }, 10 | { 11 | "revision": "45be5b04b3c14e0fb4b8", 12 | "url": "/extension-data-driven-parameters/2.0.0/static/js/2.6e32bc5d.chunk.js" 13 | }, 14 | { 15 | "revision": "f91160f4b9f466811a79", 16 | "url": "/extension-data-driven-parameters/2.0.0/static/js/main.8c9ad036.chunk.js" 17 | }, 18 | { 19 | "revision": "c673bd0018bb6cffcb9f", 20 | "url": "/extension-data-driven-parameters/2.0.0/static/js/runtime~main.717e2416.js" 21 | } 22 | ]); -------------------------------------------------------------------------------- /docs/2.0.0/service-worker.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to your Workbox-powered service worker! 3 | * 4 | * You'll need to register this file in your web app and you should 5 | * disable HTTP caching for this file too. 6 | * See https://goo.gl/nhQhGp 7 | * 8 | * The rest of the code is auto-generated. Please don't update this file 9 | * directly; instead, make changes to your Workbox build configuration 10 | * and re-run your build process. 11 | * See https://goo.gl/2aRDsh 12 | */ 13 | 14 | importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js"); 15 | 16 | importScripts( 17 | "/extension-data-driven-parameters/2.0.0/precache-manifest.dc7e0c72d8caeec99a4b170eb6b8ad0f.js" 18 | ); 19 | 20 | self.addEventListener('message', (event) => { 21 | if (event.data && event.data.type === 'SKIP_WAITING') { 22 | self.skipWaiting(); 23 | } 24 | }); 25 | 26 | workbox.core.clientsClaim(); 27 | 28 | /** 29 | * The workboxSW.precacheAndRoute() method efficiently caches and responds to 30 | * requests for URLs in the manifest. 31 | * See https://goo.gl/S9QRab 32 | */ 33 | self.__precacheManifest = [].concat(self.__precacheManifest || []); 34 | workbox.precaching.precacheAndRoute(self.__precacheManifest, {}); 35 | 36 | workbox.routing.registerNavigationRoute(workbox.precaching.getCacheKeyForURL("/extension-data-driven-parameters/2.0.0/index.html"), { 37 | 38 | blacklist: [/^\/_/,/\/[^\/]+\.[^\/]+$/], 39 | }); 40 | -------------------------------------------------------------------------------- /docs/2.0.0/static/css/main.a0b18684.chunk.css: -------------------------------------------------------------------------------- 1 | body,html{font-family:Benton Sans,Arial,Helvetica,sans-serif;font-size:12px;color:rgba(0,0,0,.8);box-sizing:border-box;overflow:hidden}#container{height:100%;width:100%}.container{display:flex;flex-direction:column;justify-content:space-between;height:100%}.content{margin-left:6px}.header{font-size:16px;padding:12px 0 12px 18px;display:flex}.header,.title{color:rgba(0,0,0,.8)}.title{font-family:Benton Sans Medium,Arial,Helvetica,sans-serif;font-size:12px;margin:30px 0 18px}p{margin:0}.selected,.selector{display:flex;min-height:26px;margin-bottom:12px}.selected{margin-left:10px;justify-content:space-between}.option,.selected{align-items:center}.option{display:flex;margin-top:12px}.footer{display:flex;align-items:flex-end;margin:0 18px}.btncluster{display:flex;justify-content:flex-end;width:100%;margin-bottom:12px}.format{display:flex;margin-top:12px}.formattext{width:130px}input[type=color]{padding:0;margin-left:6px;border:1px solid #666;box-shadow:none;width:16px;height:16px;border-radius:50%;outline:0}::-webkit-color-swatch{border:none}.tooltip{position:relative;display:inline-block;margin-left:5px;padding-top:2px}.tooltip .tooltiptext{visibility:hidden;border:1px solid #d4d4d4;border-radius:1px;background:#fff;font-size:10px;padding:8px;width:200px;position:absolute;z-index:1;right:-100px;top:20px}.tooltip:hover .tooltiptext{visibility:visible}.tooltiptext ol{padding:0 8px;margin:0}.tooltiptext li{margin-top:8px}.parameter{width:100%;font-family:Benton Sans,Arial,Helvetica,sans-serif;font-size:12px;padding-left:6px;border:1px solid #cbcbcb}.parameter option{padding:2px 2px 1px;height:20px;display:flex;align-items:center}.singleParameter{width:100%;min-height:20px!important}.dropdown-select{flex:1 1;margin-left:0;width:"100%"}.delimiter-text-field>input{font-family:Benton Sans,Arial,Helvetica,sans-serif;padding-right:0;text-align:center}select::-ms-expand{visibility:hidden}body,html{margin:0;padding:0;height:100%;width:100%;color:#585858;border:0}.icontainer{font-size:18px;background:#fafafa;display:flex;justify-content:center;align-items:center;height:100%}.box{background:#fff;max-width:1250px;margin:20px;display:flex;box-shadow:2px 4px 8px rgba(102,162,222,.15)}.left{background:-webkit-gradient(linear,right top,left bottom,from(#02b3a4),to(#66a2de));background:-webkit-linear-gradient(top right,#02b3a4,#66a2de);background:linear-gradient(to bottom left,#02b3a4,#66a2de);width:450px;color:#fff;font-size:20px;font-family:Benton Sans,Arial,Helvetica,sans-serif}.left,.right{padding:40px;display:flex;align-items:center;align-content:center;justify-content:flex-start;flex-wrap:wrap}.iheader{font-size:64px;font-family:Bookman Old Style,Arial,Helvetica,sans-serif;margin:10px 0;line-height:54px}.big{font-size:28px;width:100%;margin:5px 0}a{color:#02b3a4;font-weight:700;text-decoration:none}a:hover{text-decoration:underline}.gh{font-size:16px;text-align:center;width:100%} 2 | /*# sourceMappingURL=main.a0b18684.chunk.css.map */ -------------------------------------------------------------------------------- /docs/2.0.0/static/css/main.a0b18684.chunk.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["style.css","home.css"],"names":[],"mappings":"AAAA,UAII,kDAAwD,CACxD,cAAe,CACf,oBAAyB,CACzB,qBAAsB,CAGtB,eACJ,CAEA,WACI,WAAY,CACZ,UACJ,CAEA,WACI,YAAa,CACb,qBAAsB,CACtB,6BAA8B,CAC9B,WACJ,CAEA,SACI,eACJ,CAEA,QACI,cAAe,CAElB,wBAA2B,CACxB,YACJ,CAEA,eALI,oBAUJ,CALA,OACI,yDAA+D,CAC/D,cAAe,CAEf,kBACJ,CAEA,EACI,QACJ,CAQA,oBALI,YAAa,CACb,eAAgB,CAChB,kBAUJ,CAPA,UACI,gBAAiB,CAGjB,6BAGJ,CAEA,kBAJI,kBAQJ,CAJA,QACI,YAAa,CAEb,eACJ,CAEA,QACI,YAAa,CACb,oBAAqB,CACxB,aACD,CAEA,YACI,YAAa,CACb,wBAAyB,CACzB,UAAW,CACX,kBACJ,CAEA,QACI,YAAa,CACb,eACJ,CAEA,YACI,WACJ,CAEA,kBAEI,SAAU,CACV,eAAgB,CAChB,qBAAyB,CACzB,eAAgB,CAChB,UAAW,CACX,WAAY,CACZ,iBAAkB,CAClB,SACJ,CAEA,uBACI,WACJ,CAEA,SACI,iBAAkB,CAClB,oBAAqB,CACrB,eAAgB,CAChB,eACJ,CAEA,sBACI,iBAAkB,CAClB,wBAAyB,CACzB,iBAAkB,CAClB,eAAgB,CAChB,cAAe,CACf,WAAY,CACZ,WAAY,CACZ,iBAAkB,CAClB,SAAU,CACV,YAAa,CACb,QACJ,CAEA,4BACI,kBACJ,CAEA,gBACI,aAAgB,CAChB,QACJ,CAEA,gBACI,cACJ,CAEA,WACI,UAAW,CACd,kDAAwD,CACxD,cAAe,CACf,gBAAgB,CAChB,wBACD,CAEA,kBACC,mBAAoB,CACpB,WAAY,CACZ,YAAY,CACZ,kBACD,CAEA,iBACI,UAAW,CACd,yBACD,CAEA,iBACI,QAAO,CACP,aAAc,CACd,YACJ,CAEA,4BACI,kDAAwD,CACxD,eAAgB,CAChB,iBACJ,CAGA,mBACI,iBACJ,CC/KA,UAEI,QAAS,CACT,SAAU,CACV,WAAY,CACZ,UAAW,CACX,aAAc,CACd,QACJ,CAEA,YACI,cAAe,CACf,kBAAmB,CACnB,YAAa,CACb,sBAAuB,CACvB,kBAAmB,CACnB,WACJ,CAEA,KACI,eAAmB,CACnB,gBAAiB,CACjB,WAAY,CACZ,YAAa,CACb,4CACJ,CAEA,MACI,mFAA6D,CAA7D,6DAA6D,CAA7D,0DAA6D,CAE7D,WAAY,CACZ,UAAc,CAMd,cAAe,CACf,kDACJ,CAEA,aAZI,YAAa,CAGb,YAAa,CACb,kBAAmB,CACnB,oBAAqB,CACrB,0BAA2B,CAC3B,cAYJ,CAEA,SACI,cAAe,CACf,wDAA8D,CAC9D,aAAgB,CAChB,gBACJ,CAEA,KACI,cAAe,CACf,UAAW,CACX,YACJ,CAEA,EACI,aAAc,CACd,eAAiB,CACjB,oBACJ,CAEA,QACI,yBACJ,CAEA,IACI,cAAe,CACf,iBAAkB,CAClB,UACJ","file":"main.a0b18684.chunk.css","sourcesContent":["html,\r\nbody {\r\n margin: 0;\r\n padding: 0;\r\n font-family: 'Benton Sans', Arial, Helvetica, sans-serif;\r\n font-size: 12px;\r\n color: rgba(0, 0, 0, 0.8);\r\n box-sizing: border-box;\r\n height: 100%;\r\n width: 100%;\r\n overflow: hidden;\r\n}\r\n\r\n#container {\r\n height: 100%;\r\n width: 100%;\r\n}\r\n\r\n.container {\r\n display: flex;\r\n flex-direction: column;\r\n justify-content: space-between;\r\n height: 100%;\r\n}\r\n\r\n.content {\r\n margin-left: 6px;\r\n}\r\n\r\n.header {\r\n font-size: 16px;\r\n color: rgba(0, 0, 0, 0.8);\r\n\tpadding: 12px 0px 12px 18px;\r\n display: flex;\r\n}\r\n\r\n.title {\r\n font-family: 'Benton Sans Medium', Arial, Helvetica, sans-serif;\r\n font-size: 12px;\r\n color: rgba(0, 0, 0, 0.8);\r\n margin: 30px 0px 18px 0px;\r\n}\r\n\r\np {\r\n margin: 0;\r\n}\r\n\r\n.selector {\r\n display: flex;\r\n min-height: 26px;\r\n margin-bottom: 12px;\r\n}\r\n\r\n.selected {\r\n margin-left: 10px;\r\n min-height: 26px;\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n margin-bottom: 12px;\r\n}\r\n\r\n.option {\r\n display: flex;\r\n align-items: center;\r\n margin-top: 12px;\r\n}\r\n\r\n.footer {\r\n display: flex;\r\n align-items: flex-end;\r\n\tmargin: 0px 18px;\r\n}\r\n\r\n.btncluster {\r\n display: flex;\r\n justify-content: flex-end;\r\n width: 100%;\r\n margin-bottom: 12px;\r\n}\r\n\r\n.format {\r\n display: flex;\r\n margin-top: 12px;\r\n}\r\n\r\n.formattext {\r\n width: 130px;\r\n}\r\n\r\ninput[type=\"color\"] {\r\n /* background-color: #fff; */\r\n padding: 0;\r\n margin-left: 6px;\r\n border: 1px solid #666666;\r\n box-shadow: none;\r\n width: 16px;\r\n height: 16px;\r\n border-radius: 50%;\r\n outline: 0;\r\n}\r\n\r\n::-webkit-color-swatch {\r\n border: none;\r\n}\r\n\r\n.tooltip {\r\n position: relative;\r\n display: inline-block;\r\n margin-left: 5px;\r\n padding-top: 2px;\r\n}\r\n\r\n.tooltip .tooltiptext {\r\n visibility: hidden;\r\n border: 1px solid #D4D4D4;\r\n border-radius: 1px;\r\n background: #fff;\r\n font-size: 10px;\r\n padding: 8px;\r\n width: 200px;\r\n position: absolute;\r\n z-index: 1;\r\n right: -100px;\r\n top: 20px;\r\n}\r\n\r\n.tooltip:hover .tooltiptext {\r\n visibility: visible;\r\n}\r\n\r\n.tooltiptext ol {\r\n padding: 0px 8px;\r\n margin: 0px;\r\n}\r\n\r\n.tooltiptext li {\r\n margin-top: 8px;\r\n}\r\n\r\n.parameter {\r\n width: 100%;\r\n\tfont-family: 'Benton Sans', Arial, Helvetica, sans-serif;\r\n\tfont-size: 12px;\r\n\tpadding-left:6px;\r\n\tborder: solid 1px #CBCBCB;\r\n}\r\n\r\n.parameter option {\r\n\tpadding: 2px 2px 1px;\r\n\theight: 20px;\r\n\tdisplay:flex;\r\n\talign-items: center;\r\n}\r\n\r\n.singleParameter {\r\n width: 100%;\r\n\tmin-height: 20px !important;\r\n}\r\n\r\n.dropdown-select {\r\n flex: 1;\r\n margin-left: 0;\r\n width: '100%';\r\n}\r\n\r\n.delimiter-text-field > input {\r\n font-family: 'Benton Sans', Arial, Helvetica, sans-serif;\r\n padding-right: 0;\r\n text-align: center;\r\n}\r\n\r\n/* Internet Explorer 10+ */\r\nselect::-ms-expand {\r\n visibility: hidden;\r\n}","html,\r\nbody {\r\n margin: 0;\r\n padding: 0;\r\n height: 100%;\r\n width: 100%;\r\n color: #585858;\r\n border: 0;\r\n}\r\n\r\n.icontainer {\r\n font-size: 18px;\r\n background: #FAFAFA;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n height: 100%;\r\n}\r\n\r\n.box {\r\n background: #ffffff;\r\n max-width: 1250px;\r\n margin: 20px;\r\n display: flex;\r\n box-shadow: 2px 4px 8px rgba(102, 162, 222, 0.15);\r\n}\r\n\r\n.left {\r\n background: linear-gradient(to bottom left, #02B3A4, #66A2DE);\r\n padding: 40px;\r\n width: 450px;\r\n color: #ffffff;\r\n display: flex;\r\n align-items: center;\r\n align-content: center;\r\n justify-content: flex-start;\r\n flex-wrap: wrap;\r\n font-size: 20px;\r\n font-family: 'Benton Sans', Arial, Helvetica, sans-serif;\r\n}\r\n\r\n.right {\r\n padding: 40px;\r\n display: flex;\r\n align-items: center;\r\n align-content: center;\r\n justify-content: flex-start;\r\n flex-wrap: wrap;\r\n}\r\n\r\n.iheader {\r\n font-size: 64px;\r\n font-family: 'Bookman Old Style', Arial, Helvetica, sans-serif;\r\n margin: 10px 0px;\r\n line-height: 54px;\r\n}\r\n\r\n.big {\r\n font-size: 28px;\r\n width: 100%;\r\n margin: 5px 0px;\r\n}\r\n\r\na {\r\n color: #02B3A4;\r\n font-weight: bold;\r\n text-decoration: none;\r\n}\r\n\r\na:hover {\r\n text-decoration: underline;\r\n}\r\n\r\n.gh {\r\n font-size: 16px;\r\n text-align: center;\r\n width: 100%;\r\n}"]} -------------------------------------------------------------------------------- /docs/2.0.0/static/js/runtime~main.717e2416.js: -------------------------------------------------------------------------------- 1 | !function(e){function r(r){for(var n,i,a=r[0],f=r[1],l=r[2],c=0,s=[];cData-Driven Parameters Extension
-------------------------------------------------------------------------------- /docs/2.1.0/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Data-Driven Parameters", 3 | "name": "Data-Driven Parameters", 4 | "icons": [{ 5 | "src": "favicon.ico", 6 | "sizes": "64x64 32x32 24x24 16x16", 7 | "type": "image/x-icon" 8 | }], 9 | "start_url": ".", 10 | "display": "standalone", 11 | "theme_color": "#000000", 12 | "background_color": "#ffffff" 13 | } -------------------------------------------------------------------------------- /docs/2.1.0/precache-manifest.03cf0849ed10715b922211b8056357c4.js: -------------------------------------------------------------------------------- 1 | self.__precacheManifest = (self.__precacheManifest || []).concat([ 2 | { 3 | "revision": "1748eeffbc5479b3e125d90193768b2f", 4 | "url": "/extension-data-driven-parameters/2.1.0/index.html" 5 | }, 6 | { 7 | "revision": "5a1eccd829a83105b24e", 8 | "url": "/extension-data-driven-parameters/2.1.0/static/css/main.673a05ca.chunk.css" 9 | }, 10 | { 11 | "revision": "09254fd0a08a7b9bf518", 12 | "url": "/extension-data-driven-parameters/2.1.0/static/js/2.51c5d46f.chunk.js" 13 | }, 14 | { 15 | "revision": "5a1eccd829a83105b24e", 16 | "url": "/extension-data-driven-parameters/2.1.0/static/js/main.bb588e6f.chunk.js" 17 | }, 18 | { 19 | "revision": "e8b8459bbc586125acd5", 20 | "url": "/extension-data-driven-parameters/2.1.0/static/js/runtime~main.0d9ba244.js" 21 | } 22 | ]); -------------------------------------------------------------------------------- /docs/2.1.0/service-worker.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to your Workbox-powered service worker! 3 | * 4 | * You'll need to register this file in your web app and you should 5 | * disable HTTP caching for this file too. 6 | * See https://goo.gl/nhQhGp 7 | * 8 | * The rest of the code is auto-generated. Please don't update this file 9 | * directly; instead, make changes to your Workbox build configuration 10 | * and re-run your build process. 11 | * See https://goo.gl/2aRDsh 12 | */ 13 | 14 | importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js"); 15 | 16 | importScripts( 17 | "/extension-data-driven-parameters/2.1.0/precache-manifest.03cf0849ed10715b922211b8056357c4.js" 18 | ); 19 | 20 | self.addEventListener('message', (event) => { 21 | if (event.data && event.data.type === 'SKIP_WAITING') { 22 | self.skipWaiting(); 23 | } 24 | }); 25 | 26 | workbox.core.clientsClaim(); 27 | 28 | /** 29 | * The workboxSW.precacheAndRoute() method efficiently caches and responds to 30 | * requests for URLs in the manifest. 31 | * See https://goo.gl/S9QRab 32 | */ 33 | self.__precacheManifest = [].concat(self.__precacheManifest || []); 34 | workbox.precaching.precacheAndRoute(self.__precacheManifest, {}); 35 | 36 | workbox.routing.registerNavigationRoute(workbox.precaching.getCacheKeyForURL("/extension-data-driven-parameters/2.1.0/index.html"), { 37 | 38 | blacklist: [/^\/_/,/\/[^/]+\.[^/]+$/], 39 | }); 40 | -------------------------------------------------------------------------------- /docs/2.1.0/static/css/main.673a05ca.chunk.css: -------------------------------------------------------------------------------- 1 | body,html{font-family:Benton Sans,Arial,Helvetica,sans-serif;font-size:12px;color:rgba(0,0,0,.8);box-sizing:border-box;overflow:hidden}#container{height:100%;width:100%}.container{display:flex;flex-direction:column;justify-content:space-between;height:100%}.content{margin-left:6px}.header{font-size:16px;padding:12px 0 12px 18px;display:flex}.header,.title{color:rgba(0,0,0,.8)}.title{font-family:Benton Sans Medium,Arial,Helvetica,sans-serif;font-size:12px;margin:30px 0 18px}p{margin:0}.selected,.selector{display:flex;min-height:26px;margin-bottom:12px}.selected{margin-left:10px;justify-content:space-between}.option,.selected{align-items:center}.option{display:flex;margin-top:12px}.footer{display:flex;align-items:flex-end;margin:0 18px}.btncluster{display:flex;justify-content:flex-end;width:100%;margin-bottom:12px}.format{display:flex;margin-top:12px}.formattext{width:130px}input[type=color]{padding:0;margin-left:6px;border:1px solid #666;box-shadow:none;width:16px;height:16px;border-radius:50%;outline:0}::-webkit-color-swatch{border:none}.tooltip{position:relative;display:inline-block;margin-left:5px;padding-top:2px}.tooltip .tooltiptext{visibility:hidden;border:1px solid #d4d4d4;border-radius:1px;background:#fff;font-size:10px;padding:8px;width:200px;position:absolute;z-index:1;right:-100px;top:20px}.tooltip:hover .tooltiptext{visibility:visible}.tooltiptext ol{padding:0 8px;margin:0}.tooltiptext li{margin-top:8px}.parameter{width:100%;font-family:Benton Sans,Arial,Helvetica,sans-serif;font-size:12px;padding-left:6px;border:1px solid #cbcbcb}.parameter option{padding:2px 2px 1px;height:20px;display:flex;align-items:center}.singleParameter{width:100%;min-height:20px!important}.dropdown-select{flex:1 1;margin-left:0;width:"100%"}.delimiter-text-field>input{font-family:Benton Sans,Arial,Helvetica,sans-serif;padding-right:0;text-align:center}select::-ms-expand{visibility:hidden}body,html{margin:0;padding:0;height:100%;width:100%;color:#585858;border:0}.icontainer{font-size:18px;background:#fafafa;display:flex;justify-content:center;align-items:center;height:100%}.box{background:#fff;max-width:1250px;margin:20px;display:flex;box-shadow:2px 4px 8px rgba(102,162,222,.15)}.left{background:-webkit-gradient(linear,right top,left bottom,from(#02b3a4),to(#66a2de));background:linear-gradient(to bottom left,#02b3a4,#66a2de);width:450px;color:#fff;font-size:20px;font-family:Benton Sans,Arial,Helvetica,sans-serif}.left,.right{padding:40px;display:flex;align-items:center;align-content:center;justify-content:flex-start;flex-wrap:wrap}.iheader{font-size:64px;font-family:Bookman Old Style,Arial,Helvetica,sans-serif;margin:10px 0;line-height:54px}.big{font-size:28px;width:100%;margin:5px 0}a{color:#02b3a4;font-weight:700;text-decoration:none}a:hover{text-decoration:underline}.gh{font-size:16px;text-align:center;width:100%} 2 | /*# sourceMappingURL=main.673a05ca.chunk.css.map */ -------------------------------------------------------------------------------- /docs/2.1.0/static/css/main.673a05ca.chunk.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["style.css","home.css"],"names":[],"mappings":"AAAA,UAII,kDAAwD,CACxD,cAAe,CACf,oBAAyB,CACzB,qBAAsB,CAGtB,eACJ,CAEA,WACI,WAAY,CACZ,UACJ,CAEA,WACI,YAAa,CACb,qBAAsB,CACtB,6BAA8B,CAC9B,WACJ,CAEA,SACI,eACJ,CAEA,QACI,cAAe,CAElB,wBAA2B,CACxB,YACJ,CAEA,eALI,oBAUJ,CALA,OACI,yDAA+D,CAC/D,cAAe,CAEf,kBACJ,CAEA,EACI,QACJ,CAQA,oBALI,YAAa,CACb,eAAgB,CAChB,kBAUJ,CAPA,UACI,gBAAiB,CAGjB,6BAGJ,CAEA,kBAJI,kBAQJ,CAJA,QACI,YAAa,CAEb,eACJ,CAEA,QACI,YAAa,CACb,oBAAqB,CACxB,aACD,CAEA,YACI,YAAa,CACb,wBAAyB,CACzB,UAAW,CACX,kBACJ,CAEA,QACI,YAAa,CACb,eACJ,CAEA,YACI,WACJ,CAEA,kBAEI,SAAU,CACV,eAAgB,CAChB,qBAAyB,CACzB,eAAgB,CAChB,UAAW,CACX,WAAY,CACZ,iBAAkB,CAClB,SACJ,CAEA,uBACI,WACJ,CAEA,SACI,iBAAkB,CAClB,oBAAqB,CACrB,eAAgB,CAChB,eACJ,CAEA,sBACI,iBAAkB,CAClB,wBAAyB,CACzB,iBAAkB,CAClB,eAAgB,CAChB,cAAe,CACf,WAAY,CACZ,WAAY,CACZ,iBAAkB,CAClB,SAAU,CACV,YAAa,CACb,QACJ,CAEA,4BACI,kBACJ,CAEA,gBACI,aAAgB,CAChB,QACJ,CAEA,gBACI,cACJ,CAEA,WACI,UAAW,CACd,kDAAwD,CACxD,cAAe,CACf,gBAAgB,CAChB,wBACD,CAEA,kBACC,mBAAoB,CACpB,WAAY,CACZ,YAAY,CACZ,kBACD,CAEA,iBACI,UAAW,CACd,yBACD,CAEA,iBACI,QAAO,CACP,aAAc,CACd,YACJ,CAEA,4BACI,kDAAwD,CACxD,eAAgB,CAChB,iBACJ,CAGA,mBACI,iBACJ,CC/KA,UAEI,QAAS,CACT,SAAU,CACV,WAAY,CACZ,UAAW,CACX,aAAc,CACd,QACJ,CAEA,YACI,cAAe,CACf,kBAAmB,CACnB,YAAa,CACb,sBAAuB,CACvB,kBAAmB,CACnB,WACJ,CAEA,KACI,eAAmB,CACnB,gBAAiB,CACjB,WAAY,CACZ,YAAa,CACb,4CACJ,CAEA,MACI,mFAA6D,CAA7D,0DAA6D,CAE7D,WAAY,CACZ,UAAc,CAMd,cAAe,CACf,kDACJ,CAEA,aAZI,YAAa,CAGb,YAAa,CACb,kBAAmB,CACnB,oBAAqB,CACrB,0BAA2B,CAC3B,cAYJ,CAEA,SACI,cAAe,CACf,wDAA8D,CAC9D,aAAgB,CAChB,gBACJ,CAEA,KACI,cAAe,CACf,UAAW,CACX,YACJ,CAEA,EACI,aAAc,CACd,eAAiB,CACjB,oBACJ,CAEA,QACI,yBACJ,CAEA,IACI,cAAe,CACf,iBAAkB,CAClB,UACJ","file":"main.673a05ca.chunk.css","sourcesContent":["html,\r\nbody {\r\n margin: 0;\r\n padding: 0;\r\n font-family: 'Benton Sans', Arial, Helvetica, sans-serif;\r\n font-size: 12px;\r\n color: rgba(0, 0, 0, 0.8);\r\n box-sizing: border-box;\r\n height: 100%;\r\n width: 100%;\r\n overflow: hidden;\r\n}\r\n\r\n#container {\r\n height: 100%;\r\n width: 100%;\r\n}\r\n\r\n.container {\r\n display: flex;\r\n flex-direction: column;\r\n justify-content: space-between;\r\n height: 100%;\r\n}\r\n\r\n.content {\r\n margin-left: 6px;\r\n}\r\n\r\n.header {\r\n font-size: 16px;\r\n color: rgba(0, 0, 0, 0.8);\r\n\tpadding: 12px 0px 12px 18px;\r\n display: flex;\r\n}\r\n\r\n.title {\r\n font-family: 'Benton Sans Medium', Arial, Helvetica, sans-serif;\r\n font-size: 12px;\r\n color: rgba(0, 0, 0, 0.8);\r\n margin: 30px 0px 18px 0px;\r\n}\r\n\r\np {\r\n margin: 0;\r\n}\r\n\r\n.selector {\r\n display: flex;\r\n min-height: 26px;\r\n margin-bottom: 12px;\r\n}\r\n\r\n.selected {\r\n margin-left: 10px;\r\n min-height: 26px;\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n margin-bottom: 12px;\r\n}\r\n\r\n.option {\r\n display: flex;\r\n align-items: center;\r\n margin-top: 12px;\r\n}\r\n\r\n.footer {\r\n display: flex;\r\n align-items: flex-end;\r\n\tmargin: 0px 18px;\r\n}\r\n\r\n.btncluster {\r\n display: flex;\r\n justify-content: flex-end;\r\n width: 100%;\r\n margin-bottom: 12px;\r\n}\r\n\r\n.format {\r\n display: flex;\r\n margin-top: 12px;\r\n}\r\n\r\n.formattext {\r\n width: 130px;\r\n}\r\n\r\ninput[type=\"color\"] {\r\n /* background-color: #fff; */\r\n padding: 0;\r\n margin-left: 6px;\r\n border: 1px solid #666666;\r\n box-shadow: none;\r\n width: 16px;\r\n height: 16px;\r\n border-radius: 50%;\r\n outline: 0;\r\n}\r\n\r\n::-webkit-color-swatch {\r\n border: none;\r\n}\r\n\r\n.tooltip {\r\n position: relative;\r\n display: inline-block;\r\n margin-left: 5px;\r\n padding-top: 2px;\r\n}\r\n\r\n.tooltip .tooltiptext {\r\n visibility: hidden;\r\n border: 1px solid #D4D4D4;\r\n border-radius: 1px;\r\n background: #fff;\r\n font-size: 10px;\r\n padding: 8px;\r\n width: 200px;\r\n position: absolute;\r\n z-index: 1;\r\n right: -100px;\r\n top: 20px;\r\n}\r\n\r\n.tooltip:hover .tooltiptext {\r\n visibility: visible;\r\n}\r\n\r\n.tooltiptext ol {\r\n padding: 0px 8px;\r\n margin: 0px;\r\n}\r\n\r\n.tooltiptext li {\r\n margin-top: 8px;\r\n}\r\n\r\n.parameter {\r\n width: 100%;\r\n\tfont-family: 'Benton Sans', Arial, Helvetica, sans-serif;\r\n\tfont-size: 12px;\r\n\tpadding-left:6px;\r\n\tborder: solid 1px #CBCBCB;\r\n}\r\n\r\n.parameter option {\r\n\tpadding: 2px 2px 1px;\r\n\theight: 20px;\r\n\tdisplay:flex;\r\n\talign-items: center;\r\n}\r\n\r\n.singleParameter {\r\n width: 100%;\r\n\tmin-height: 20px !important;\r\n}\r\n\r\n.dropdown-select {\r\n flex: 1;\r\n margin-left: 0;\r\n width: '100%';\r\n}\r\n\r\n.delimiter-text-field > input {\r\n font-family: 'Benton Sans', Arial, Helvetica, sans-serif;\r\n padding-right: 0;\r\n text-align: center;\r\n}\r\n\r\n/* Internet Explorer 10+ */\r\nselect::-ms-expand {\r\n visibility: hidden;\r\n}","html,\r\nbody {\r\n margin: 0;\r\n padding: 0;\r\n height: 100%;\r\n width: 100%;\r\n color: #585858;\r\n border: 0;\r\n}\r\n\r\n.icontainer {\r\n font-size: 18px;\r\n background: #FAFAFA;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n height: 100%;\r\n}\r\n\r\n.box {\r\n background: #ffffff;\r\n max-width: 1250px;\r\n margin: 20px;\r\n display: flex;\r\n box-shadow: 2px 4px 8px rgba(102, 162, 222, 0.15);\r\n}\r\n\r\n.left {\r\n background: linear-gradient(to bottom left, #02B3A4, #66A2DE);\r\n padding: 40px;\r\n width: 450px;\r\n color: #ffffff;\r\n display: flex;\r\n align-items: center;\r\n align-content: center;\r\n justify-content: flex-start;\r\n flex-wrap: wrap;\r\n font-size: 20px;\r\n font-family: 'Benton Sans', Arial, Helvetica, sans-serif;\r\n}\r\n\r\n.right {\r\n padding: 40px;\r\n display: flex;\r\n align-items: center;\r\n align-content: center;\r\n justify-content: flex-start;\r\n flex-wrap: wrap;\r\n}\r\n\r\n.iheader {\r\n font-size: 64px;\r\n font-family: 'Bookman Old Style', Arial, Helvetica, sans-serif;\r\n margin: 10px 0px;\r\n line-height: 54px;\r\n}\r\n\r\n.big {\r\n font-size: 28px;\r\n width: 100%;\r\n margin: 5px 0px;\r\n}\r\n\r\na {\r\n color: #02B3A4;\r\n font-weight: bold;\r\n text-decoration: none;\r\n}\r\n\r\na:hover {\r\n text-decoration: underline;\r\n}\r\n\r\n.gh {\r\n font-size: 16px;\r\n text-align: center;\r\n width: 100%;\r\n}"]} -------------------------------------------------------------------------------- /docs/2.1.0/static/js/runtime~main.0d9ba244.js: -------------------------------------------------------------------------------- 1 | !function(e){function r(r){for(var n,i,a=r[0],f=r[1],l=r[2],c=0,s=[];cData-Driven Parameters Extension
-------------------------------------------------------------------------------- /docs/2.latest/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Data-Driven Parameters", 3 | "name": "Data-Driven Parameters", 4 | "icons": [{ 5 | "src": "favicon.ico", 6 | "sizes": "64x64 32x32 24x24 16x16", 7 | "type": "image/x-icon" 8 | }], 9 | "start_url": ".", 10 | "display": "standalone", 11 | "theme_color": "#000000", 12 | "background_color": "#ffffff" 13 | } -------------------------------------------------------------------------------- /docs/2.latest/precache-manifest.d75aafc2866f2a41c3713ec81c2e13c8.js: -------------------------------------------------------------------------------- 1 | self.__precacheManifest = (self.__precacheManifest || []).concat([ 2 | { 3 | "revision": "088fb8c76e828a8f268a7df1720d7021", 4 | "url": "/extension-data-driven-parameters/2.latest/index.html" 5 | }, 6 | { 7 | "revision": "fac8b5bc0a696e7a392e", 8 | "url": "/extension-data-driven-parameters/2.latest/static/css/main.673a05ca.chunk.css" 9 | }, 10 | { 11 | "revision": "09254fd0a08a7b9bf518", 12 | "url": "/extension-data-driven-parameters/2.latest/static/js/2.51c5d46f.chunk.js" 13 | }, 14 | { 15 | "revision": "fac8b5bc0a696e7a392e", 16 | "url": "/extension-data-driven-parameters/2.latest/static/js/main.3aea75ac.chunk.js" 17 | }, 18 | { 19 | "revision": "1c7dd2cc5b7c2c522bac", 20 | "url": "/extension-data-driven-parameters/2.latest/static/js/runtime~main.e725b044.js" 21 | } 22 | ]); -------------------------------------------------------------------------------- /docs/2.latest/service-worker.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to your Workbox-powered service worker! 3 | * 4 | * You'll need to register this file in your web app and you should 5 | * disable HTTP caching for this file too. 6 | * See https://goo.gl/nhQhGp 7 | * 8 | * The rest of the code is auto-generated. Please don't update this file 9 | * directly; instead, make changes to your Workbox build configuration 10 | * and re-run your build process. 11 | * See https://goo.gl/2aRDsh 12 | */ 13 | 14 | importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js"); 15 | 16 | importScripts( 17 | "/extension-data-driven-parameters/2.latest/precache-manifest.d75aafc2866f2a41c3713ec81c2e13c8.js" 18 | ); 19 | 20 | self.addEventListener('message', (event) => { 21 | if (event.data && event.data.type === 'SKIP_WAITING') { 22 | self.skipWaiting(); 23 | } 24 | }); 25 | 26 | workbox.core.clientsClaim(); 27 | 28 | /** 29 | * The workboxSW.precacheAndRoute() method efficiently caches and responds to 30 | * requests for URLs in the manifest. 31 | * See https://goo.gl/S9QRab 32 | */ 33 | self.__precacheManifest = [].concat(self.__precacheManifest || []); 34 | workbox.precaching.precacheAndRoute(self.__precacheManifest, {}); 35 | 36 | workbox.routing.registerNavigationRoute(workbox.precaching.getCacheKeyForURL("/extension-data-driven-parameters/2.latest/index.html"), { 37 | 38 | blacklist: [/^\/_/,/\/[^/]+\.[^/]+$/], 39 | }); 40 | -------------------------------------------------------------------------------- /docs/2.latest/static/css/main.673a05ca.chunk.css: -------------------------------------------------------------------------------- 1 | body,html{font-family:Benton Sans,Arial,Helvetica,sans-serif;font-size:12px;color:rgba(0,0,0,.8);box-sizing:border-box;overflow:hidden}#container{height:100%;width:100%}.container{display:flex;flex-direction:column;justify-content:space-between;height:100%}.content{margin-left:6px}.header{font-size:16px;padding:12px 0 12px 18px;display:flex}.header,.title{color:rgba(0,0,0,.8)}.title{font-family:Benton Sans Medium,Arial,Helvetica,sans-serif;font-size:12px;margin:30px 0 18px}p{margin:0}.selected,.selector{display:flex;min-height:26px;margin-bottom:12px}.selected{margin-left:10px;justify-content:space-between}.option,.selected{align-items:center}.option{display:flex;margin-top:12px}.footer{display:flex;align-items:flex-end;margin:0 18px}.btncluster{display:flex;justify-content:flex-end;width:100%;margin-bottom:12px}.format{display:flex;margin-top:12px}.formattext{width:130px}input[type=color]{padding:0;margin-left:6px;border:1px solid #666;box-shadow:none;width:16px;height:16px;border-radius:50%;outline:0}::-webkit-color-swatch{border:none}.tooltip{position:relative;display:inline-block;margin-left:5px;padding-top:2px}.tooltip .tooltiptext{visibility:hidden;border:1px solid #d4d4d4;border-radius:1px;background:#fff;font-size:10px;padding:8px;width:200px;position:absolute;z-index:1;right:-100px;top:20px}.tooltip:hover .tooltiptext{visibility:visible}.tooltiptext ol{padding:0 8px;margin:0}.tooltiptext li{margin-top:8px}.parameter{width:100%;font-family:Benton Sans,Arial,Helvetica,sans-serif;font-size:12px;padding-left:6px;border:1px solid #cbcbcb}.parameter option{padding:2px 2px 1px;height:20px;display:flex;align-items:center}.singleParameter{width:100%;min-height:20px!important}.dropdown-select{flex:1 1;margin-left:0;width:"100%"}.delimiter-text-field>input{font-family:Benton Sans,Arial,Helvetica,sans-serif;padding-right:0;text-align:center}select::-ms-expand{visibility:hidden}body,html{margin:0;padding:0;height:100%;width:100%;color:#585858;border:0}.icontainer{font-size:18px;background:#fafafa;display:flex;justify-content:center;align-items:center;height:100%}.box{background:#fff;max-width:1250px;margin:20px;display:flex;box-shadow:2px 4px 8px rgba(102,162,222,.15)}.left{background:-webkit-gradient(linear,right top,left bottom,from(#02b3a4),to(#66a2de));background:linear-gradient(to bottom left,#02b3a4,#66a2de);width:450px;color:#fff;font-size:20px;font-family:Benton Sans,Arial,Helvetica,sans-serif}.left,.right{padding:40px;display:flex;align-items:center;align-content:center;justify-content:flex-start;flex-wrap:wrap}.iheader{font-size:64px;font-family:Bookman Old Style,Arial,Helvetica,sans-serif;margin:10px 0;line-height:54px}.big{font-size:28px;width:100%;margin:5px 0}a{color:#02b3a4;font-weight:700;text-decoration:none}a:hover{text-decoration:underline}.gh{font-size:16px;text-align:center;width:100%} 2 | /*# sourceMappingURL=main.673a05ca.chunk.css.map */ -------------------------------------------------------------------------------- /docs/2.latest/static/css/main.673a05ca.chunk.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["style.css","home.css"],"names":[],"mappings":"AAAA,UAII,kDAAwD,CACxD,cAAe,CACf,oBAAyB,CACzB,qBAAsB,CAGtB,eACJ,CAEA,WACI,WAAY,CACZ,UACJ,CAEA,WACI,YAAa,CACb,qBAAsB,CACtB,6BAA8B,CAC9B,WACJ,CAEA,SACI,eACJ,CAEA,QACI,cAAe,CAElB,wBAA2B,CACxB,YACJ,CAEA,eALI,oBAUJ,CALA,OACI,yDAA+D,CAC/D,cAAe,CAEf,kBACJ,CAEA,EACI,QACJ,CAQA,oBALI,YAAa,CACb,eAAgB,CAChB,kBAUJ,CAPA,UACI,gBAAiB,CAGjB,6BAGJ,CAEA,kBAJI,kBAQJ,CAJA,QACI,YAAa,CAEb,eACJ,CAEA,QACI,YAAa,CACb,oBAAqB,CACxB,aACD,CAEA,YACI,YAAa,CACb,wBAAyB,CACzB,UAAW,CACX,kBACJ,CAEA,QACI,YAAa,CACb,eACJ,CAEA,YACI,WACJ,CAEA,kBAEI,SAAU,CACV,eAAgB,CAChB,qBAAyB,CACzB,eAAgB,CAChB,UAAW,CACX,WAAY,CACZ,iBAAkB,CAClB,SACJ,CAEA,uBACI,WACJ,CAEA,SACI,iBAAkB,CAClB,oBAAqB,CACrB,eAAgB,CAChB,eACJ,CAEA,sBACI,iBAAkB,CAClB,wBAAyB,CACzB,iBAAkB,CAClB,eAAgB,CAChB,cAAe,CACf,WAAY,CACZ,WAAY,CACZ,iBAAkB,CAClB,SAAU,CACV,YAAa,CACb,QACJ,CAEA,4BACI,kBACJ,CAEA,gBACI,aAAgB,CAChB,QACJ,CAEA,gBACI,cACJ,CAEA,WACI,UAAW,CACd,kDAAwD,CACxD,cAAe,CACf,gBAAgB,CAChB,wBACD,CAEA,kBACC,mBAAoB,CACpB,WAAY,CACZ,YAAY,CACZ,kBACD,CAEA,iBACI,UAAW,CACd,yBACD,CAEA,iBACI,QAAO,CACP,aAAc,CACd,YACJ,CAEA,4BACI,kDAAwD,CACxD,eAAgB,CAChB,iBACJ,CAGA,mBACI,iBACJ,CC/KA,UAEI,QAAS,CACT,SAAU,CACV,WAAY,CACZ,UAAW,CACX,aAAc,CACd,QACJ,CAEA,YACI,cAAe,CACf,kBAAmB,CACnB,YAAa,CACb,sBAAuB,CACvB,kBAAmB,CACnB,WACJ,CAEA,KACI,eAAmB,CACnB,gBAAiB,CACjB,WAAY,CACZ,YAAa,CACb,4CACJ,CAEA,MACI,mFAA6D,CAA7D,0DAA6D,CAE7D,WAAY,CACZ,UAAc,CAMd,cAAe,CACf,kDACJ,CAEA,aAZI,YAAa,CAGb,YAAa,CACb,kBAAmB,CACnB,oBAAqB,CACrB,0BAA2B,CAC3B,cAYJ,CAEA,SACI,cAAe,CACf,wDAA8D,CAC9D,aAAgB,CAChB,gBACJ,CAEA,KACI,cAAe,CACf,UAAW,CACX,YACJ,CAEA,EACI,aAAc,CACd,eAAiB,CACjB,oBACJ,CAEA,QACI,yBACJ,CAEA,IACI,cAAe,CACf,iBAAkB,CAClB,UACJ","file":"main.673a05ca.chunk.css","sourcesContent":["html,\r\nbody {\r\n margin: 0;\r\n padding: 0;\r\n font-family: 'Benton Sans', Arial, Helvetica, sans-serif;\r\n font-size: 12px;\r\n color: rgba(0, 0, 0, 0.8);\r\n box-sizing: border-box;\r\n height: 100%;\r\n width: 100%;\r\n overflow: hidden;\r\n}\r\n\r\n#container {\r\n height: 100%;\r\n width: 100%;\r\n}\r\n\r\n.container {\r\n display: flex;\r\n flex-direction: column;\r\n justify-content: space-between;\r\n height: 100%;\r\n}\r\n\r\n.content {\r\n margin-left: 6px;\r\n}\r\n\r\n.header {\r\n font-size: 16px;\r\n color: rgba(0, 0, 0, 0.8);\r\n\tpadding: 12px 0px 12px 18px;\r\n display: flex;\r\n}\r\n\r\n.title {\r\n font-family: 'Benton Sans Medium', Arial, Helvetica, sans-serif;\r\n font-size: 12px;\r\n color: rgba(0, 0, 0, 0.8);\r\n margin: 30px 0px 18px 0px;\r\n}\r\n\r\np {\r\n margin: 0;\r\n}\r\n\r\n.selector {\r\n display: flex;\r\n min-height: 26px;\r\n margin-bottom: 12px;\r\n}\r\n\r\n.selected {\r\n margin-left: 10px;\r\n min-height: 26px;\r\n display: flex;\r\n justify-content: space-between;\r\n align-items: center;\r\n margin-bottom: 12px;\r\n}\r\n\r\n.option {\r\n display: flex;\r\n align-items: center;\r\n margin-top: 12px;\r\n}\r\n\r\n.footer {\r\n display: flex;\r\n align-items: flex-end;\r\n\tmargin: 0px 18px;\r\n}\r\n\r\n.btncluster {\r\n display: flex;\r\n justify-content: flex-end;\r\n width: 100%;\r\n margin-bottom: 12px;\r\n}\r\n\r\n.format {\r\n display: flex;\r\n margin-top: 12px;\r\n}\r\n\r\n.formattext {\r\n width: 130px;\r\n}\r\n\r\ninput[type=\"color\"] {\r\n /* background-color: #fff; */\r\n padding: 0;\r\n margin-left: 6px;\r\n border: 1px solid #666666;\r\n box-shadow: none;\r\n width: 16px;\r\n height: 16px;\r\n border-radius: 50%;\r\n outline: 0;\r\n}\r\n\r\n::-webkit-color-swatch {\r\n border: none;\r\n}\r\n\r\n.tooltip {\r\n position: relative;\r\n display: inline-block;\r\n margin-left: 5px;\r\n padding-top: 2px;\r\n}\r\n\r\n.tooltip .tooltiptext {\r\n visibility: hidden;\r\n border: 1px solid #D4D4D4;\r\n border-radius: 1px;\r\n background: #fff;\r\n font-size: 10px;\r\n padding: 8px;\r\n width: 200px;\r\n position: absolute;\r\n z-index: 1;\r\n right: -100px;\r\n top: 20px;\r\n}\r\n\r\n.tooltip:hover .tooltiptext {\r\n visibility: visible;\r\n}\r\n\r\n.tooltiptext ol {\r\n padding: 0px 8px;\r\n margin: 0px;\r\n}\r\n\r\n.tooltiptext li {\r\n margin-top: 8px;\r\n}\r\n\r\n.parameter {\r\n width: 100%;\r\n\tfont-family: 'Benton Sans', Arial, Helvetica, sans-serif;\r\n\tfont-size: 12px;\r\n\tpadding-left:6px;\r\n\tborder: solid 1px #CBCBCB;\r\n}\r\n\r\n.parameter option {\r\n\tpadding: 2px 2px 1px;\r\n\theight: 20px;\r\n\tdisplay:flex;\r\n\talign-items: center;\r\n}\r\n\r\n.singleParameter {\r\n width: 100%;\r\n\tmin-height: 20px !important;\r\n}\r\n\r\n.dropdown-select {\r\n flex: 1;\r\n margin-left: 0;\r\n width: '100%';\r\n}\r\n\r\n.delimiter-text-field > input {\r\n font-family: 'Benton Sans', Arial, Helvetica, sans-serif;\r\n padding-right: 0;\r\n text-align: center;\r\n}\r\n\r\n/* Internet Explorer 10+ */\r\nselect::-ms-expand {\r\n visibility: hidden;\r\n}","html,\r\nbody {\r\n margin: 0;\r\n padding: 0;\r\n height: 100%;\r\n width: 100%;\r\n color: #585858;\r\n border: 0;\r\n}\r\n\r\n.icontainer {\r\n font-size: 18px;\r\n background: #FAFAFA;\r\n display: flex;\r\n justify-content: center;\r\n align-items: center;\r\n height: 100%;\r\n}\r\n\r\n.box {\r\n background: #ffffff;\r\n max-width: 1250px;\r\n margin: 20px;\r\n display: flex;\r\n box-shadow: 2px 4px 8px rgba(102, 162, 222, 0.15);\r\n}\r\n\r\n.left {\r\n background: linear-gradient(to bottom left, #02B3A4, #66A2DE);\r\n padding: 40px;\r\n width: 450px;\r\n color: #ffffff;\r\n display: flex;\r\n align-items: center;\r\n align-content: center;\r\n justify-content: flex-start;\r\n flex-wrap: wrap;\r\n font-size: 20px;\r\n font-family: 'Benton Sans', Arial, Helvetica, sans-serif;\r\n}\r\n\r\n.right {\r\n padding: 40px;\r\n display: flex;\r\n align-items: center;\r\n align-content: center;\r\n justify-content: flex-start;\r\n flex-wrap: wrap;\r\n}\r\n\r\n.iheader {\r\n font-size: 64px;\r\n font-family: 'Bookman Old Style', Arial, Helvetica, sans-serif;\r\n margin: 10px 0px;\r\n line-height: 54px;\r\n}\r\n\r\n.big {\r\n font-size: 28px;\r\n width: 100%;\r\n margin: 5px 0px;\r\n}\r\n\r\na {\r\n color: #02B3A4;\r\n font-weight: bold;\r\n text-decoration: none;\r\n}\r\n\r\na:hover {\r\n text-decoration: underline;\r\n}\r\n\r\n.gh {\r\n font-size: 16px;\r\n text-align: center;\r\n width: 100%;\r\n}"]} -------------------------------------------------------------------------------- /docs/2.latest/static/js/runtime~main.e725b044.js: -------------------------------------------------------------------------------- 1 | !function(e){function r(r){for(var n,a,i=r[0],l=r[1],f=r[2],c=0,s=[];cData-Driven Parameters Extension
-------------------------------------------------------------------------------- /docs/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Data-Driven Parameters", 3 | "name": "Data-Driven Parameters", 4 | "icons": [{ 5 | "src": "favicon.ico", 6 | "sizes": "64x64 32x32 24x24 16x16", 7 | "type": "image/x-icon" 8 | }], 9 | "start_url": ".", 10 | "display": "standalone", 11 | "theme_color": "#000000", 12 | "background_color": "#ffffff" 13 | } -------------------------------------------------------------------------------- /docs/precache-manifest.8f5c5c66632ab1c8eb2b9ab4c458256a.js: -------------------------------------------------------------------------------- 1 | self.__precacheManifest = (self.__precacheManifest || []).concat([ 2 | { 3 | "revision": "cf10014de9c1b3deba70f406fa002a1e", 4 | "url": "/extension-data-driven-parameters/index.html" 5 | }, 6 | { 7 | "revision": "25bb9a99b7d45da3060b", 8 | "url": "/extension-data-driven-parameters/static/css/main.cb967471.chunk.css" 9 | }, 10 | { 11 | "revision": "4c8bd9850eaae52f864b", 12 | "url": "/extension-data-driven-parameters/static/js/2.bbca4fae.chunk.js" 13 | }, 14 | { 15 | "revision": "25bb9a99b7d45da3060b", 16 | "url": "/extension-data-driven-parameters/static/js/main.ae08df8d.chunk.js" 17 | }, 18 | { 19 | "revision": "a4a54d5146f2dbde5fc0", 20 | "url": "/extension-data-driven-parameters/static/js/runtime~main.01d56cb3.js" 21 | } 22 | ]); -------------------------------------------------------------------------------- /docs/service-worker.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Welcome to your Workbox-powered service worker! 3 | * 4 | * You'll need to register this file in your web app and you should 5 | * disable HTTP caching for this file too. 6 | * See https://goo.gl/nhQhGp 7 | * 8 | * The rest of the code is auto-generated. Please don't update this file 9 | * directly; instead, make changes to your Workbox build configuration 10 | * and re-run your build process. 11 | * See https://goo.gl/2aRDsh 12 | */ 13 | 14 | importScripts("https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js"); 15 | 16 | importScripts( 17 | "/extension-data-driven-parameters/precache-manifest.8f5c5c66632ab1c8eb2b9ab4c458256a.js" 18 | ); 19 | 20 | self.addEventListener('message', (event) => { 21 | if (event.data && event.data.type === 'SKIP_WAITING') { 22 | self.skipWaiting(); 23 | } 24 | }); 25 | 26 | workbox.core.clientsClaim(); 27 | 28 | /** 29 | * The workboxSW.precacheAndRoute() method efficiently caches and responds to 30 | * requests for URLs in the manifest. 31 | * See https://goo.gl/S9QRab 32 | */ 33 | self.__precacheManifest = [].concat(self.__precacheManifest || []); 34 | workbox.precaching.precacheAndRoute(self.__precacheManifest, {}); 35 | 36 | workbox.routing.registerNavigationRoute(workbox.precaching.getCacheKeyForURL("/extension-data-driven-parameters/index.html"), { 37 | 38 | blacklist: [/^\/_/,/\/[^\/]+\.[^\/]+$/], 39 | }); 40 | -------------------------------------------------------------------------------- /docs/static/css/main.cb967471.chunk.css: -------------------------------------------------------------------------------- 1 | body,html{font-family:Benton Sans,Arial,Helvetica,sans-serif;font-size:12px;color:rgba(0,0,0,.8);box-sizing:border-box;overflow:hidden}#container{height:100%;width:100%}.container{padding:0 18px;display:flex;flex-direction:column;justify-content:space-between;height:100%}.content{margin-left:10px}.header{font-size:16px;margin-top:12px;display:flex}.header,.title{color:rgba(0,0,0,.8)}.title{font-family:Benton Sans Medium,Arial,Helvetica,sans-serif;font-size:12px;margin:30px 0 18px}p{margin:0}.selected,.selector{display:flex;min-height:26px;margin-bottom:12px}.selected{margin-left:10px;justify-content:space-between}.option,.selected{align-items:center}.option{display:flex;margin-top:12px}.footer{display:flex;align-items:flex-end}.btncluster{display:flex;justify-content:flex-end;align-items:center;width:100%;margin-bottom:12px}.format{display:flex;margin-top:12px}.formattext{width:130px}input[type=color]{padding:0;margin-left:6px;border:1px solid #666;box-shadow:none;width:16px;height:16px;border-radius:50%;outline:0}::-webkit-color-swatch{border:none}.tooltip{position:relative;display:inline-block;margin-left:5px;padding-top:2px}.tooltip .tooltiptext{visibility:hidden;border:1px solid #d4d4d4;border-radius:1px;background:#fff;font-size:10px;padding:8px;width:200px;position:absolute;z-index:1;right:-100px;top:20px}.tooltip:hover .tooltiptext{visibility:visible}.tooltiptext ol{padding:0 8px;margin:0}.tooltiptext li{margin-top:8px}.parameter{width:100%;font-family:Benton Sans,Arial,Helvetica,sans-serif;font-size:12px;padding-left:6px;border:1px solid #cbcbcb}.parameter option{padding:2px 2px 1px;height:20px;display:flex;align-items:center}.singleParameter{width:100%}.dropdown-select{flex:1 1;margin-left:0;width:"100%"}.delimiter-text-field>input{font-family:Benton Sans,Arial,Helvetica,sans-serif;padding-right:0;text-align:center}select::-ms-expand{visibility:hidden}body,html{margin:0;padding:0;height:100%;width:100%;color:#585858;border:0}.icontainer{font-size:18px;background:#fafafa;display:flex;justify-content:center;align-items:center;height:100%}.box{background:#fff;max-width:1250px;margin:20px;display:flex;box-shadow:2px 4px 8px rgba(102,162,222,.15)}.left{background:-webkit-gradient(linear,right top,left bottom,from(#02b3a4),to(#66a2de));background:-webkit-linear-gradient(top right,#02b3a4,#66a2de);background:linear-gradient(to bottom left,#02b3a4,#66a2de);width:450px;color:#fff;font-size:20px;font-family:Benton Sans,Arial,Helvetica,sans-serif}.left,.right{padding:40px;display:flex;align-items:center;align-content:center;justify-content:flex-start;flex-wrap:wrap}.iheader{font-size:64px;font-family:Bookman Old Style,Arial,Helvetica,sans-serif;margin:10px 0;line-height:54px}.big{font-size:28px;width:100%;margin:5px 0}a{color:#02b3a4;font-weight:700;text-decoration:none}a:hover{text-decoration:underline}.gh{font-size:16px;text-align:center;width:100%} 2 | /*# sourceMappingURL=main.cb967471.chunk.css.map */ -------------------------------------------------------------------------------- /docs/static/css/main.cb967471.chunk.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["style.css","home.css"],"names":[],"mappings":"AAAA,UAII,kDAAwD,CACxD,cAAe,CACf,oBAAyB,CACzB,qBAAsB,CAGtB,eACJ,CAEA,WACI,WAAY,CACZ,UACJ,CAEA,WACI,cAA0B,CAC1B,YAAa,CACb,qBAAsB,CACtB,6BAA8B,CAC9B,WACJ,CAEA,SACI,gBACJ,CAEA,QACI,cAAe,CAEf,eAAgB,CAChB,YACJ,CAEA,eALI,oBAUJ,CALA,OACI,yDAA+D,CAC/D,cAAe,CAEf,kBACJ,CAEA,EACI,QACJ,CAQA,oBALI,YAAa,CACb,eAAgB,CAChB,kBAUJ,CAPA,UACI,gBAAiB,CAGjB,6BAGJ,CAEA,kBAJI,kBAQJ,CAJA,QACI,YAAa,CAEb,eACJ,CAEA,QACI,YAAa,CACb,oBACJ,CAEA,YACI,YAAa,CACb,wBAAyB,CAC5B,kBAAmB,CAChB,UAAW,CACX,kBACJ,CAEA,QACI,YAAa,CACb,eACJ,CAEA,YACI,WACJ,CAEA,kBAEI,SAAU,CACV,eAAgB,CAChB,qBAAyB,CACzB,eAAgB,CAChB,UAAW,CACX,WAAY,CACZ,iBAAkB,CAClB,SACJ,CAEA,uBACI,WACJ,CAEA,SACI,iBAAkB,CAClB,oBAAqB,CACrB,eAAgB,CAChB,eACJ,CAEA,sBACI,iBAAkB,CAClB,wBAAyB,CACzB,iBAAkB,CAClB,eAAgB,CAChB,cAAe,CACf,WAAY,CACZ,WAAY,CACZ,iBAAkB,CAClB,SAAU,CACV,YAAa,CACb,QACJ,CAEA,4BACI,kBACJ,CAEA,gBACI,aAAgB,CAChB,QACJ,CAEA,gBACI,cACJ,CAEA,WACI,UAAW,CACd,kDAAwD,CACxD,cAAe,CACf,gBAAgB,CAChB,wBACD,CAEA,kBACC,mBAAoB,CACpB,WAAY,CACZ,YAAY,CACZ,kBACD,CAEA,iBACI,UACJ,CAEA,iBACI,QAAO,CACP,aAAc,CACd,YACJ,CAEA,4BACI,kDAAwD,CACxD,eAAgB,CAChB,iBACJ,CAGA,mBACI,iBACJ,CC/KA,UAEI,QAAS,CACT,SAAU,CACV,WAAY,CACZ,UAAW,CACX,aAAc,CACd,QACJ,CAEA,YACI,cAAe,CACf,kBAAmB,CACnB,YAAa,CACb,sBAAuB,CACvB,kBAAmB,CACnB,WACJ,CAEA,KACI,eAAmB,CACnB,gBAAiB,CACjB,WAAY,CACZ,YAAa,CACb,4CACJ,CAEA,MACI,mFAA6D,CAA7D,6DAA6D,CAA7D,0DAA6D,CAE7D,WAAY,CACZ,UAAc,CAMd,cAAe,CACf,kDACJ,CAEA,aAZI,YAAa,CAGb,YAAa,CACb,kBAAmB,CACnB,oBAAqB,CACrB,0BAA2B,CAC3B,cAYJ,CAEA,SACI,cAAe,CACf,wDAA8D,CAC9D,aAAgB,CAChB,gBACJ,CAEA,KACI,cAAe,CACf,UAAW,CACX,YACJ,CAEA,EACI,aAAc,CACd,eAAiB,CACjB,oBACJ,CAEA,QACI,yBACJ,CAEA,IACI,cAAe,CACf,iBAAkB,CAClB,UACJ","file":"main.cb967471.chunk.css","sourcesContent":["html,\nbody {\n margin: 0;\n padding: 0;\n font-family: 'Benton Sans', Arial, Helvetica, sans-serif;\n font-size: 12px;\n color: rgba(0, 0, 0, 0.8);\n box-sizing: border-box;\n height: 100%;\n width: 100%;\n overflow: hidden;\n}\n\n#container {\n height: 100%;\n width: 100%;\n}\n\n.container {\n padding: 0px 18px 0px 18px;\n display: flex;\n flex-direction: column;\n justify-content: space-between;\n height: 100%;\n}\n\n.content {\n margin-left: 10px;\n}\n\n.header {\n font-size: 16px;\n color: rgba(0, 0, 0, 0.8);\n margin-top: 12px;\n display: flex;\n}\n\n.title {\n font-family: 'Benton Sans Medium', Arial, Helvetica, sans-serif;\n font-size: 12px;\n color: rgba(0, 0, 0, 0.8);\n margin: 30px 0px 18px 0px;\n}\n\np {\n margin: 0;\n}\n\n.selector {\n display: flex;\n min-height: 26px;\n margin-bottom: 12px;\n}\n\n.selected {\n margin-left: 10px;\n min-height: 26px;\n display: flex;\n justify-content: space-between;\n align-items: center;\n margin-bottom: 12px;\n}\n\n.option {\n display: flex;\n align-items: center;\n margin-top: 12px;\n}\n\n.footer {\n display: flex;\n align-items: flex-end;\n}\n\n.btncluster {\n display: flex;\n justify-content: flex-end;\n\talign-items: center;\n width: 100%;\n margin-bottom: 12px;\n}\n\n.format {\n display: flex;\n margin-top: 12px;\n}\n\n.formattext {\n width: 130px;\n}\n\ninput[type=\"color\"] {\n /* background-color: #fff; */\n padding: 0;\n margin-left: 6px;\n border: 1px solid #666666;\n box-shadow: none;\n width: 16px;\n height: 16px;\n border-radius: 50%;\n outline: 0;\n}\n\n::-webkit-color-swatch {\n border: none;\n}\n\n.tooltip {\n position: relative;\n display: inline-block;\n margin-left: 5px;\n padding-top: 2px;\n}\n\n.tooltip .tooltiptext {\n visibility: hidden;\n border: 1px solid #D4D4D4;\n border-radius: 1px;\n background: #fff;\n font-size: 10px;\n padding: 8px;\n width: 200px;\n position: absolute;\n z-index: 1;\n right: -100px;\n top: 20px;\n}\n\n.tooltip:hover .tooltiptext {\n visibility: visible;\n}\n\n.tooltiptext ol {\n padding: 0px 8px;\n margin: 0px;\n}\n\n.tooltiptext li {\n margin-top: 8px;\n}\n\n.parameter {\n width: 100%;\n\tfont-family: 'Benton Sans', Arial, Helvetica, sans-serif;\n\tfont-size: 12px;\n\tpadding-left:6px;\n\tborder: solid 1px #CBCBCB;\n}\n\n.parameter option {\n\tpadding: 2px 2px 1px;\n\theight: 20px;\n\tdisplay:flex;\n\talign-items: center;\n}\n\n.singleParameter {\n width: 100%;\n}\n\n.dropdown-select {\n flex: 1;\n margin-left: 0;\n width: '100%';\n}\n\n.delimiter-text-field > input {\n font-family: 'Benton Sans', Arial, Helvetica, sans-serif;\n padding-right: 0;\n text-align: center;\n}\n\n/* Internet Explorer 10+ */\nselect::-ms-expand {\n visibility: hidden;\n}","html,\nbody {\n margin: 0;\n padding: 0;\n height: 100%;\n width: 100%;\n color: #585858;\n border: 0;\n}\n\n.icontainer {\n font-size: 18px;\n background: #FAFAFA;\n display: flex;\n justify-content: center;\n align-items: center;\n height: 100%;\n}\n\n.box {\n background: #ffffff;\n max-width: 1250px;\n margin: 20px;\n display: flex;\n box-shadow: 2px 4px 8px rgba(102, 162, 222, 0.15);\n}\n\n.left {\n background: linear-gradient(to bottom left, #02B3A4, #66A2DE);\n padding: 40px;\n width: 450px;\n color: #ffffff;\n display: flex;\n align-items: center;\n align-content: center;\n justify-content: flex-start;\n flex-wrap: wrap;\n font-size: 20px;\n font-family: 'Benton Sans', Arial, Helvetica, sans-serif;\n}\n\n.right {\n padding: 40px;\n display: flex;\n align-items: center;\n align-content: center;\n justify-content: flex-start;\n flex-wrap: wrap;\n}\n\n.iheader {\n font-size: 64px;\n font-family: 'Bookman Old Style', Arial, Helvetica, sans-serif;\n margin: 10px 0px;\n line-height: 54px;\n}\n\n.big {\n font-size: 28px;\n width: 100%;\n margin: 5px 0px;\n}\n\na {\n color: #02B3A4;\n font-weight: bold;\n text-decoration: none;\n}\n\na:hover {\n text-decoration: underline;\n}\n\n.gh {\n font-size: 16px;\n text-align: center;\n width: 100%;\n}"]} -------------------------------------------------------------------------------- /docs/static/js/main.ae08df8d.chunk.js: -------------------------------------------------------------------------------- 1 | (window.webpackJsonp=window.webpackJsonp||[]).push([[0],{133:function(e,t,a){},134:function(e,t,a){},139:function(e,t,a){"use strict";a.r(t);var n=a(13),l=a(14),i=a(16),s=a(15),r=a(17),o=(a(74),a(0)),c=a(69),u=a(18),d=a(72),m=a(1),h=function(e){return o.createElement("div",{className:"selected"},o.createElement("p",null,o.createElement("i",null,"The ",e.selecting," ",o.createElement("b",null,e.selected)," has been selected")),o.createElement(m.Button,{onClick:e.onClear,style:{visibility:e.nextConfig?"hidden":"visible",marginLeft:"12px"}},"Clear"))};h.displayName="Selected";var f=function(e){var t={className:"dropdown-select",disabled:!e.enabled,kind:"line",onChange:e.onChange,onSelect:e.onChange,value:e.selected},a={disabled:!e.enabled||""===e.selected,kind:"filledGreen",onClick:e.onClick,style:{marginLeft:"12px"}};return o.createElement("div",{className:"selector"},o.createElement(m.DropdownSelect,t,e.list.map(function(e){return o.createElement("option",{key:e},e)})),o.createElement(m.Button,a,"Set"))};f.displayName="Selector";var g,p=function(e){return o.createElement(o.Fragment,null,o.createElement("span",null,"Select a ",e.selecting),function(e){var t=e.config,a=e.enabled,n=e.list,l=e.nextConfig,i=e.onChange,s=e.onClear,r=e.onClick,c=e.selected,u=e.selecting;return t?o.createElement(h,{nextConfig:l,onClear:s,selected:c,selecting:u}):o.createElement(f,{enabled:a,list:n,onChange:i,onClick:r,selected:c})}(e))};p.displayName="Setting";var b,w,y="Loading...",v=function(e){function t(){var e,a;Object(n.a)(this,t);for(var l=arguments.length,r=new Array(l),o=0;o0?e.setState({param_enabled:!0,param_list:a,parameter:a[0]}):e.setState({param_enabled:!1,param_list:["No open input parameters found!"],parameter:"No open input parameters found!"})})}},{key:"testWSSettings",value:function(){var e=window.tableau.extensions.settings.getAll();this.state.configured?g.worksheets.find(function(t){return t.name===e.selWorksheet})?(this.setState({worksheet:e.selWorksheet,ws_config:!0,ws_enabled:!1}),this.testFieldSettings()):(this.populateWS(),this.setState({configured:!1})):this.populateWS()}},{key:"populateWS",value:function(){this.setState({worksheet:y,ws_list:[y]});var e=[],t=!0,a=!1,n=void 0;try{for(var l,i=g.worksheets[Symbol.iterator]();!(t=(l=i.next()).done);t=!0){var s=l.value;e.push(s.name)}}catch(r){a=!0,n=r}finally{try{t||null==i.return||i.return()}finally{if(a)throw n}}e.length>0?this.setState({worksheet:e[0],ws_enabled:!0,ws_list:e}):this.setState({worksheet:"No worksheets found!",ws_enabled:!1,ws_list:["No worksheets found!"]})}},{key:"testFieldSettings",value:function(){var e=this,t=window.tableau.extensions.settings.getAll();this.state.configured?g.worksheets.find(function(t){return t.name===e.state.worksheet}).getSummaryDataAsync().then(function(a){a.columns.find(function(e){return e.fieldName===t.selField})?e.setState({configured:!0,field:t.selField,field_config:!0,field_enabled:!1}):(e.populateFieldList(),e.setState({configured:!1}))}):this.populateFieldList()}},{key:"populateFieldList",value:function(){var e,t=this;this.setState({field:y,field_list:[y]}),g.findParameterAsync(this.state.parameter).then(function(a){return e=a.dataType,g.worksheets.find(function(e){return e.name===t.state.worksheet}).getSummaryDataAsync()}).then(function(a){var n=[],l=!0,i=!1,s=void 0;try{for(var r,o=a.columns[Symbol.iterator]();!(l=(r=o.next()).done);l=!0){var c=r.value;c.dataType===e&&n.push(c.fieldName)}}catch(u){i=!0,s=u}finally{try{l||null==o.return||o.return()}finally{if(i)throw s}}n.length>0?t.setState({field:n[0],field_enabled:!0,field_list:n}):t.setState({field:"No fields found that match parameter!",field_enabled:!1,field_list:["No fields found that match parameter!"]})})}},{key:"componentWillMount",value:function(){var e=this;window.tableau.extensions.initializeDialogAsync().then(function(){g=window.tableau.extensions.dashboardContent.dashboard;var t=window.tableau.extensions.settings.getAll();"true"===t.configured?(e.setState({autoUpdate:"true"===t.autoUpdate||!1,bg:t.bg||"#ffffff",configured:!0,dataType:t.dataType,delimiter:t.delimiter||"|",ignoreSelection:"true"===t.ignoreSelection||!1,includeAllValue:"true"===t.includeAllValue||!1,multiselect:"true"===t.multiselect||!1,sort:t.sort||"asc",txt:t.txt||"#000000",useFormattedValues:"true"===t.useFormattedValues||!1}),e.testParamSettings()):e.populateParamList()})}},{key:"render",value:function(){return o.createElement(o.Fragment,null,o.createElement("div",{className:"container"},o.createElement("div",null,o.createElement("div",{className:"header"},"Data-Driven Parameter Configuration",o.createElement("div",{className:"tooltip"},o.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",id:"Dialogs_x5F_Info",width:"15",height:"15",viewBox:"0 0 15 15"},o.createElement("rect",{id:"Line",x:"7",y:"6",width:"1",height:"5",fillRule:"evenodd",clipRule:"evenodd",fill:"#666766"}),o.createElement("rect",{id:"Dot_2_",x:"7",y:"4",width:"1",height:"1",fillRule:"evenodd",clipRule:"evenodd",fill:"#666766"}),o.createElement("path",{id:"Circle",d:"M7.5,1C3.9,1,1,3.9,1,7.5S3.9,14,7.5,14 S14,11.1,14,7.5S11.1,1,7.5,1z M7.5,13C4.5,13,2,10.5,2,7.5C2,4.5,4.5,2,7.5,2S13,4.5,13,7.5C13,10.5,10.5,13,7.5,13z",fillRule:"evenodd",clipRule:"evenodd",fill:"#666766"})),o.createElement("span",{className:"tooltiptext"},o.createElement("b",null,"How to Use"),o.createElement("ol",null,o.createElement("li",null,'Select a Tableau parameter to manipulate. This parameter must already exists and must allow "all" values.'),o.createElement("li",null,"Select a worksheet with the data you want to use in your parameter."),o.createElement("li",null,"Select a field to use to populate the parameter. Field data type must match the data type of parameter.")),o.createElement("br",null),o.createElement("p",null,"Note: Mac Desktop 2018.3 and lower, please use arrow keys and 'Enter' to select options")))),o.createElement("div",{className:"title",style:{marginTop:"18px"}},"Configure Parameter"),o.createElement("div",{className:"content"},o.createElement(p,{selecting:"parameter",onClick:this.setParam,onClear:this.clearParam,config:this.state.param_config,nextConfig:this.state.ws_config,selected:this.state.parameter,enabled:this.state.param_enabled&&!this.state.param_config,list:this.state.param_list,onChange:this.paramChange}),o.createElement(p,{selecting:"worksheet",onClick:this.setWS,onClear:this.clearWS,config:this.state.ws_config,nextConfig:this.state.field_config,selected:this.state.worksheet,enabled:this.state.ws_enabled,list:this.state.ws_list,onChange:this.wsChange}),o.createElement(p,{selecting:"field",onClick:this.setField,onClear:this.clearField,config:this.state.field_config,selected:this.state.field,enabled:this.state.field_enabled,list:this.state.field_list,onChange:this.fieldChange})),o.createElement("div",{className:"title"},"Options"),o.createElement("div",{className:"content"},o.createElement("div",{className:"option"},o.createElement(m.Checkbox,{checked:!this.state.ignoreSelection,onChange:this.ignoreSelectionChange,style:{flexGrow:1}},"Filter parameter list based on worksheet selections")),o.createElement("div",{className:"option"},o.createElement(m.Checkbox,{checked:this.state.useFormattedValues,onChange:this.aliasChange,style:{flexGrow:1}},"Use aliased values")),o.createElement("div",{className:"option"},o.createElement(m.Checkbox,{checked:this.state.autoUpdate,onChange:this.autoUpdateChange,style:{flexGrow:1}},"Automatically reset values on load.")),o.createElement("div",{className:"option"},"Sorting:",o.createElement(m.Radio,{checked:"asc"===this.state.sort,onChange:this.sortChange,name:"sorting",value:"asc",style:{margin:"0px 12px"}},"Ascending (A-Z)"),o.createElement(m.Radio,{checked:"desc"===this.state.sort,onChange:this.sortChange,name:"sorting",value:"desc",style:{margin:"0px 12px"}},"Descending (Z-A)")),o.createElement("div",{className:"option"},o.createElement("p",null,o.createElement("i",null,"For use with string parameters only:"))),o.createElement("div",{className:"option"},o.createElement(m.Checkbox,{disabled:"string"!==this.state.dataType,checked:this.state.includeAllValue,onChange:this.allChange,style:{flexGrow:1}},'Include "(All)" in parameter list ',o.createElement("br",null)," ",o.createElement("i",null,"Note: This is only a placeholder for calculations."))),o.createElement("div",{className:"option"},o.createElement(m.Checkbox,{disabled:"string"!==this.state.dataType,checked:this.state.multiselect,onChange:this.multiselectChange,style:{marginRight:"10px"}},"Allow for multiple selections."),o.createElement("span",{children:"Delimiter:",style:{marginRight:"5px"}}),o.createElement(m.TextField,{kind:"line",onChange:this.delimiterChange,className:"delimiter-text-field",value:this.state.delimiter,disabled:!this.state.multiselect||"string"!==this.state.dataType,maxLength:1,style:{width:20}}))),o.createElement("div",{className:"title"},"Formatting"),o.createElement("div",{className:"content"},o.createElement("div",{className:"format"},o.createElement("div",{className:"formattext"},"Background Color"),o.createElement("div",null,o.createElement("input",{type:"color",value:this.state.bg,onChange:this.bgChange,style:{backgroundColor:this.state.bg}}))),o.createElement("div",{className:"format"},o.createElement("div",{className:"formattext"},"Text Color"),o.createElement("div",null,o.createElement("input",{type:"color",value:this.state.txt,onChange:this.txtChange,style:{backgroundColor:this.state.txt}}))))),o.createElement("div",{className:"footer"},o.createElement("div",{className:"btncluster"},o.createElement(m.Button,{onClick:this.clearSettings,style:{marginRight:"auto"}},"Clear Settings"),o.createElement("a",{href:"https://extensiongallery.tableau.com/products/27",target:"_blank",rel:"noopener noreferrer"},"Version 2.0 available"),o.createElement(m.Button,{kind:"filledGreen",onClick:this.submit,disabled:!this.state.configured||!this.state.ws_config,style:{marginLeft:"12px"}},"OK")))))}}]),t}(o.Component),E=(a(133),"Parameter needs configuration");function x(e){var t=function(e){var t=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(e);return t?{b:parseInt(t[3],16),g:parseInt(t[2],16),r:parseInt(t[1],16)}:null}(e);return t?"rgb(".concat(Math.min(Math.floor(t.r/2)+127,255),", ").concat(Math.min(Math.floor(t.g/2)+127,255),", ").concat(Math.min(Math.floor(t.b/2)+127,255),")"):"#ffffff"}var S=function(e){function t(){var e,a;Object(n.a)(this,t);for(var l=arguments.length,r=new Array(l),o=0;o0.2%", 35 | "not dead", 36 | "not op_mini all" 37 | ], 38 | "development": [ 39 | "ie 11", 40 | "last 1 chrome version", 41 | "last 1 firefox version", 42 | "last 1 safari version" 43 | ] 44 | }, 45 | "devDependencies": { 46 | "@types/enzyme": "^3.10.3", 47 | "enzyme": "^3.10.0", 48 | "enzyme-adapter-react-16": "^1.14.0" 49 | }, 50 | "resolutions": { 51 | "ssri": "^6.0.2", 52 | "is-svg": "^4.2.2", 53 | "react-dev-utils": "^11.0.4", 54 | "immer": "^8.0.1", 55 | "node-notifier": "^8.0.1", 56 | "object-path": "^0.11.5", 57 | "node-forge": "^0.10.0", 58 | "url-parse": "^1.5.1", 59 | "hosted-git-info": "^2.8.9", 60 | "postcss": "^8.2.10", 61 | "lodash": "^4.17.21", 62 | "browserslist": "^4.16.5", 63 | "dns-packet": "^1.3.4" 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tableau/extension-data-driven-parameters/3a97c522fb3cf36bd389366ef7626066f679345f/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Data-Driven Parameters Extension 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Data-Driven Parameters", 3 | "name": "Data-Driven Parameters", 4 | "icons": [{ 5 | "src": "favicon.ico", 6 | "sizes": "64x64 32x32 24x24 16x16", 7 | "type": "image/x-icon" 8 | }], 9 | "start_url": ".", 10 | "display": "standalone", 11 | "theme_color": "#000000", 12 | "background_color": "#ffffff" 13 | } -------------------------------------------------------------------------------- /sandboxed/DataDrivenParameters_Sandboxed.trex: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | en_US 5 | 6 | Automatically update your parameters based on your data! 7 | 8 | 0.9 9 | 10 | https://extensions.tableauusercontent.com/sandbox/data-driven-parameters/index.html 11 | 12 | iVBORw0KGgoAAAANSUhEUgAAAEYAAABGCAYAAABxLuKEAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFHGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDE5LTAyLTA2VDE0OjE4OjQ5LTA4OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAxOS0wMi0wNlQxNDoxOToxNS0wODowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAxOS0wMi0wNlQxNDoxOToxNS0wODowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo3ZjJhNDI0YS02YzY2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 13 | 14 | 15 | 16 | 17 | 18 | 19 | Data-Driven Parameter 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /sandboxed/DataDrivenParameters_Sandboxed_Test.trex: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | en_US 5 | 6 | Automatically update your parameters based on your data! 7 | 8 | 0.9 9 | 10 | http://localhost:8080/sandbox/data-driven-parameters/index.html 11 | 12 | iVBORw0KGgoAAAANSUhEUgAAAEYAAABGCAYAAABxLuKEAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFHGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDUgNzkuMTYzNDk5LCAyMDE4LzA4LzEzLTE2OjQwOjIyICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1sbnM6cGhvdG9zaG9wPSJodHRwOi8vbnMuYWRvYmUuY29tL3Bob3Rvc2hvcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOSAoV2luZG93cykiIHhtcDpDcmVhdGVEYXRlPSIyMDE5LTAyLTA2VDE0OjE4OjQ5LTA4OjAwIiB4bXA6TW9kaWZ5RGF0ZT0iMjAxOS0wMi0wNlQxNDoxOToxNS0wODowMCIgeG1wOk1ldGFkYXRhRGF0ZT0iMjAxOS0wMi0wNlQxNDoxOToxNS0wODowMCIgZGM6Zm9ybWF0PSJpbWFnZS9wbmciIHBob3Rvc2hvcDpDb2xvck1vZGU9IjMiIHBob3Rvc2hvcDpJQ0NQcm9maWxlPSJzUkdCIElFQzYxOTY2LTIuMSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo3ZjJhNDI0YS02YzY2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 13 | 14 | 15 | 16 | 17 | 18 | 19 | Data-Driven Parameter 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /sandboxed/config-overrides.js: -------------------------------------------------------------------------------- 1 | const multipleEntry = require('react-app-rewire-multiple-entry')( 2 | [{ 3 | entry: 'src/entry_index.tsx', 4 | template: 'public/index.html', 5 | outPath: '/index.html' 6 | }, 7 | { 8 | entry: 'src/entry_config.tsx', 9 | template: 'public/config.html', 10 | outPath: '/config.html' 11 | } 12 | ] 13 | ); 14 | 15 | module.exports = { 16 | webpack: function (config, env) { 17 | multipleEntry.addMultiEntry(config); 18 | return config; 19 | }, 20 | devServer: function (configFunction) { 21 | multipleEntry.addEntryProxy(configFunction); 22 | return configFunction; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /sandboxed/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "port": 8080, 3 | "extensions": { 4 | "data-driven-parameters": { 5 | "path": "./build" 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /sandboxed/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "data-driven-parameters", 3 | "version": "1.0.0", 4 | "private": true, 5 | "homepage": ".", 6 | "dependencies": { 7 | "@tableau/extensions-api-types": "^1.3.1", 8 | "@tableau/tabextsandbox": "^1.0.1", 9 | "@tableau/tableau-ui": "^2.2.1", 10 | "@types/jest": "^24.0.15", 11 | "@types/node": "^12.6.0", 12 | "@types/react": "^16.8.23", 13 | "@types/react-dom": "^16.8.4", 14 | "@types/react-router-dom": "^4.3.4", 15 | "react": "^16.8.6", 16 | "react-app-polyfill": "^1.0.1", 17 | "react-dom": "^16.8.6", 18 | "react-router-dom": "^5.0.1", 19 | "react-scripts": "^3.0.1", 20 | "typescript": "^3.5.2" 21 | }, 22 | "scripts": { 23 | "start": "react-app-rewired start", 24 | "build": "react-app-rewired build", 25 | "test": "react-app-rewired test", 26 | "eject": "react-scripts eject" 27 | }, 28 | "eslintConfig": { 29 | "extends": "react-app" 30 | }, 31 | "browserslist": { 32 | "production": [ 33 | ">0.2%", 34 | "not dead", 35 | "not op_mini all" 36 | ], 37 | "development": [ 38 | "ie 11", 39 | "last 1 chrome version", 40 | "last 1 firefox version", 41 | "last 1 safari version" 42 | ] 43 | }, 44 | "devDependencies": { 45 | "@types/enzyme": "^3.10.3", 46 | "enzyme": "^3.10.0", 47 | "enzyme-adapter-react-16": "^1.14.0", 48 | "react-app-rewire-multiple-entry": "^1.0.1", 49 | "react-app-rewired": "^2.1.3" 50 | }, 51 | "resolutions": { 52 | "**/**/minimist": "^1.2.2", 53 | "ssri": "^6.0.2", 54 | "is-svg": "^4.2.2", 55 | "react-dev-utils": "^11.0.4", 56 | "immer": "^8.0.1", 57 | "node-notifier": "^8.0.1", 58 | "object-path": "^0.11.5", 59 | "node-forge": "^0.10.0", 60 | "url-parse": "^1.5.1", 61 | "hosted-git-info": "^2.8.9", 62 | "postcss": "^8.2.10", 63 | "lodash": "^4.17.21", 64 | "browserslist": "^4.16.5", 65 | "dns-packet": "^1.3.4" 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /sandboxed/public/config.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Configure Data-Driven Parameters Extension 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /sandboxed/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tableau/extension-data-driven-parameters/3a97c522fb3cf36bd389366ef7626066f679345f/sandboxed/public/favicon.ico -------------------------------------------------------------------------------- /sandboxed/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Data-Driven Parameters Extension 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /sandboxed/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "Data-Driven Parameters", 3 | "name": "Data-Driven Parameters", 4 | "icons": [{ 5 | "src": "favicon.ico", 6 | "sizes": "64x64 32x32 24x24 16x16", 7 | "type": "image/x-icon" 8 | }], 9 | "start_url": ".", 10 | "display": "standalone", 11 | "theme_color": "#000000", 12 | "background_color": "#ffffff" 13 | } -------------------------------------------------------------------------------- /sandboxed/src/DataDrivenParameter.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import './style.css'; 3 | import { Button, DropdownSelect } from '@tableau/tableau-ui'; 4 | const tableau = window.tableau; 5 | 6 | let unregister = [() => { }, () => { }, () => { }, () => { }]; 7 | 8 | interface State { 9 | allLabel: string, 10 | applyButton: boolean, 11 | applyButtonLabel: string, 12 | bg: string, 13 | configured: boolean, 14 | currentVal: any[], 15 | disabled: boolean, 16 | firstInit: boolean, 17 | list: any[], 18 | multiselect: boolean, 19 | } 20 | 21 | const NeedsConfiguring: any = { value: 'Parameter needs configuration', displayValue: 'Parameter needs configuration' }; 22 | const Loading: any = { value: 'Loading...', displayValue: 'Loading...' }; 23 | 24 | // Switches base URL based on where extension is being hosted 25 | const baseURL: string = window.location.origin.includes('localhost:3000') ? window.location.origin : '.'; 26 | 27 | function fakeWhiteOverlay(hex: string) { 28 | const rgb = hexToRgb(hex); 29 | if (rgb) { 30 | return `rgb(${Math.min(Math.floor(rgb.r / 2) + 127, 255)}, ${Math.min(Math.floor(rgb.g / 2) + 127, 255)}, ${Math.min(Math.floor(rgb.b / 2) + 127, 255)})`; 31 | } else { 32 | return '#ffffff'; 33 | } 34 | } 35 | 36 | function hexToRgb(hex: string) { 37 | const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); 38 | return result ? { 39 | b: parseInt(result[3], 16), 40 | g: parseInt(result[2], 16), 41 | r: parseInt(result[1], 16), 42 | } : null; 43 | } 44 | 45 | class DataDrivenParameter extends React.Component { 46 | public readonly state: State = { 47 | allLabel: 'Apply', 48 | applyButton: false, 49 | applyButtonLabel: '(All)', 50 | bg: '#ffffff', 51 | configured: false, 52 | currentVal: [Loading], 53 | disabled: true, 54 | firstInit: true, 55 | list: [Loading], 56 | multiselect: false, 57 | }; 58 | 59 | // Pops open the configure page 60 | public configure = (): void => { 61 | const popupUrl = `${baseURL}/config.html`; 62 | const payload = ''; 63 | tableau.extensions.ui.displayDialogAsync(popupUrl, payload, { height: 610, width: 450 }).then((closePayload: string) => { 64 | this.setup(); 65 | }).catch((error: any) => { 66 | if (tableau.extensions.settings.get('configured') !== 'true') { 67 | this.setState({ 68 | currentVal: [NeedsConfiguring], 69 | disabled: true, 70 | list: [NeedsConfiguring], 71 | }); 72 | } 73 | switch (error.errorCode) { 74 | case tableau.ErrorCodes.DialogClosedByUser: 75 | console.log('Dialog was closed by user.'); 76 | break; 77 | default: 78 | console.error(error.message); 79 | } 80 | }); 81 | } 82 | 83 | // Locates the parameter to update 84 | public findParameter() { 85 | const settings = tableau.extensions.settings.getAll(); 86 | const dashboard = tableau.extensions.dashboardContent.dashboard; 87 | dashboard.findParameterAsync(settings.selParam).then((parameter: any) => { 88 | if (!parameter || parameter.allowableValues.type !== 'all') { 89 | this.setState({ 90 | currentVal: [NeedsConfiguring], 91 | disabled: true, 92 | list: [NeedsConfiguring], 93 | }); 94 | } else { 95 | this.getParamData(); 96 | this.resetListeners(); 97 | } 98 | }); 99 | } 100 | 101 | // Gets the values from the selected field 102 | public getParamData = (): void => { 103 | const settings = tableau.extensions.settings.getAll(); 104 | const dashboard = tableau.extensions.dashboardContent.dashboard; 105 | const worksheet = dashboard.worksheets.find((ws: any) => ws.name === settings.selWorksheet); 106 | if (!worksheet) { 107 | this.setState({ 108 | currentVal: [NeedsConfiguring], 109 | disabled: true, 110 | list: [NeedsConfiguring], 111 | }); 112 | } else { 113 | worksheet.getSummaryDataAsync({ ignoreSelection: settings.ignoreSelection === 'true' }).then((dataTable: any) => { 114 | this.populateParam(dataTable); 115 | }); 116 | } 117 | } 118 | 119 | // Pulls domain of selected field 120 | public populateParam(dataTable: any) { 121 | const settings = tableau.extensions.settings.getAll(); 122 | const field = dataTable.columns.find((column: any) => column.fieldName === settings.selField); 123 | this.setState({ 124 | currentVal: [Loading], 125 | disabled: true, 126 | list: [Loading], 127 | }); 128 | 129 | if (!field) { 130 | this.setState({ 131 | currentVal: [NeedsConfiguring], 132 | disabled: true, 133 | list: [NeedsConfiguring], 134 | }); 135 | } else { 136 | this.createList(field, dataTable); 137 | } 138 | } 139 | 140 | // Populate list with values from data source 141 | public createList(field: any, dataTable: any) { 142 | const settings = tableau.extensions.settings.getAll(); 143 | const displayField = dataTable.columns.find((column: any) => column.fieldName === settings.displayField); 144 | 145 | let list: any[] = []; 146 | for (const row of dataTable.data) { 147 | const value = settings.useFormattedValues === 'true' ? row[field.index].formattedValue : row[field.index].value; 148 | let displayValue = value; 149 | if (displayField && settings.showDisplayValues === 'true') { 150 | displayValue = row[displayField.index].formattedValue 151 | } 152 | list.push({ 153 | displayValue, 154 | value, 155 | }); 156 | } 157 | 158 | // Remove duplicates 159 | list = list.filter((item, index, array) => array.indexOf(array.find(i => i.value === item.value)) === index); 160 | 161 | if (settings.dataType && (settings.dataType === 'int' || settings.dataType === 'float')) { 162 | // Convert to numbers for correct sort 163 | list = list.map((item) => ({ value: Number(item.value), displayValue: item.displayValue })) 164 | // Sort according to settings (numerical) 165 | if (settings.sort && settings.sort === 'desc') { 166 | list.sort((a, b) => b.value - a.value); 167 | } else { 168 | list.sort((a, b) => a.value - b.value); 169 | } 170 | if (settings.dataType === 'float') { 171 | list = list.map((item) => ({ value: item.value.toLocaleString(tableau.extensions.environment.locale), displayValue: item.displayValue })); 172 | } 173 | } else { 174 | // Sort according to settings 175 | if (settings.sort && settings.sort === 'desc') { 176 | list.sort((a, b) => a.value < b.value ? 1 : -1); 177 | } else { 178 | list.sort((a, b) => a.value > b.value ? 1 : -1); 179 | } 180 | } 181 | 182 | // Add '(All)' according to settings 183 | if (settings.includeAllValue === 'true') { 184 | list.unshift({ value: this.state.allLabel, displayValue: this.state.allLabel }); 185 | } 186 | 187 | this.setState({ 188 | list, 189 | }, this.setCurrentValue); 190 | 191 | } 192 | 193 | // Determine whether to use current param value or first value of list based on settings 194 | public setCurrentValue = (): void => { 195 | const settings = tableau.extensions.settings.getAll(); 196 | const dashboard = tableau.extensions.dashboardContent.dashboard; 197 | const list = this.state.list; 198 | let currentVal: any[] = []; 199 | dashboard.findParameterAsync(settings.selParam).then((parameter: any) => { 200 | if ((this.state.firstInit && settings.autoUpdate === 'true')) { 201 | // Then push new values 202 | currentVal = [(settings.includeAllValue === 'true' ? list[1].value : list[0].value)]; 203 | } else { 204 | // Then match parameter value 205 | if (settings.multiselect === 'true') { 206 | const tablist = []; 207 | for (const value of parameter.currentValue.value.split(settings.delimiter)) { 208 | if (list.find((v: any) => v.value.toString() === value || v.value === value)) { 209 | tablist.push(value); 210 | } 211 | } 212 | currentVal = tablist; 213 | } else { 214 | if (list.find((v: any) => v.value.toString() === parameter.currentValue.value || v.value === parameter.currentValue.value)) { 215 | currentVal = [parameter.currentValue.value]; 216 | } 217 | } 218 | if (currentVal.length === 0) { 219 | // If no match, use first value 220 | currentVal = [(settings.includeAllValue === 'true' ? list[1].value : list[0].value)]; 221 | } 222 | } 223 | 224 | parameter.changeValueAsync(settings.multiselect ? currentVal.join(settings.delimiter) : currentVal.toString()).then(console.log); 225 | 226 | this.setState({ 227 | disabled: false, 228 | firstInit: false, 229 | currentVal 230 | }); 231 | }); 232 | } 233 | 234 | // Adds event listener to worksheet and parameter 235 | public async registerListeners() { 236 | const settings = tableau.extensions.settings.getAll(); 237 | const dashboard = tableau.extensions.dashboardContent.dashboard; 238 | const worksheet = dashboard.worksheets.find((ws: any) => ws.name === settings.selWorksheet); 239 | dashboard.findParameterAsync(settings.selParam).then((parameter: any) => { 240 | if (!worksheet || !parameter) { 241 | this.setState({ 242 | currentVal: [NeedsConfiguring], 243 | disabled: true, 244 | list: [NeedsConfiguring], 245 | }); 246 | } else { 247 | if (!settings.updateOnSelectionFix || settings.updateOnSelectionFix === 'true') { 248 | unregister[0] = worksheet.addEventListener(tableau.TableauEventType.FilterChanged, this.getParamData); 249 | unregister[1] = worksheet.addEventListener(tableau.TableauEventType.MarkSelectionChanged, this.getParamData); 250 | } 251 | if (settings.matchParam === 'true') { 252 | unregister[2] = parameter.addEventListener(tableau.TableauEventType.ParameterChanged, this.matchListener); 253 | } 254 | if (settings.listenParam === 'true') { 255 | dashboard.findParameterAsync(settings.listenParamName).then((updateParameter: any) => { 256 | unregister[3] = updateParameter.addEventListener(tableau.TableauEventType.ParameterChanged, this.getParamData); 257 | }) 258 | } 259 | } 260 | }); 261 | } 262 | 263 | public matchListener = (): void => { 264 | const settings = tableau.extensions.settings.getAll(); 265 | const dashboard = tableau.extensions.dashboardContent.dashboard; 266 | dashboard.findParameterAsync(settings.selParam).then((parameter: any) => { 267 | const currentVal = this.state.multiselect ? parameter.currentValue.value.split(settings.delimiter) : [parameter.currentValue.value]; 268 | this.setState({ 269 | currentVal, 270 | }); 271 | }); 272 | } 273 | 274 | public resetListeners() { 275 | for (let fn of unregister) { 276 | fn(); 277 | } 278 | this.registerListeners(); 279 | } 280 | 281 | // Updates the parameter based on selection in Data-Driven Parameter 282 | public updateParam = (e: any) => { 283 | const settings = tableau.extensions.settings.getAll(); 284 | const dashboard = tableau.extensions.dashboardContent.dashboard; 285 | const values: any = []; 286 | let newValue: any; 287 | for (const opt of e.target.options) { 288 | if (opt.selected) { 289 | values.push(opt.value); 290 | } 291 | } 292 | this.setState({ currentVal: values }); 293 | newValue = values.join(settings.delimiter); 294 | dashboard.findParameterAsync(settings.selParam).then((parameter: any) => { 295 | if (!parameter) { 296 | this.setState({ 297 | currentVal: [NeedsConfiguring], 298 | disabled: true, 299 | list: [NeedsConfiguring], 300 | }); 301 | } else { 302 | if (settings.applyButton === 'false') { 303 | parameter.changeValueAsync(newValue).then(console.log); 304 | } 305 | } 306 | 307 | if (settings.updateOnChange === 'true') { 308 | // Don't update list if on multi-select, ends up being confusing. 309 | if (!this.state.multiselect) { 310 | this.getParamData(); 311 | } 312 | } 313 | }); 314 | } 315 | 316 | public apply = (): void => { 317 | const settings = tableau.extensions.settings.getAll(); 318 | const dashboard = tableau.extensions.dashboardContent.dashboard; 319 | dashboard.findParameterAsync(settings.selParam).then((parameter: any) => { 320 | parameter.changeValueAsync(this.state.currentVal.join(settings.delimiter)).then(console.log); 321 | }); 322 | } 323 | 324 | public setup() { 325 | const settings = tableau.extensions.settings.getAll(); 326 | document.body.style.backgroundColor = settings.bg; 327 | document.body.style.color = settings.txt; 328 | this.setState({ 329 | allLabel: settings.allLabel || '(All)', 330 | applyButton: settings.applyButton === 'true' || false, 331 | applyButtonLabel: settings.applyButtonLabel || 'Apply', 332 | bg: (settings.bg ? fakeWhiteOverlay(settings.bg) : '#ffffff'), 333 | configured: true, 334 | multiselect: settings.multiselect === 'true' || false, 335 | }); 336 | this.findParameter(); 337 | } 338 | 339 | // Once we have mounted, we call to initialize 340 | public componentWillMount() { 341 | tableau.extensions.initializeAsync({ configure: this.configure }).then(() => { 342 | const settings = tableau.extensions.settings.getAll(); 343 | if (settings.configured === 'true') { 344 | this.setup(); 345 | } else { 346 | this.setState({ 347 | currentVal: [NeedsConfiguring], 348 | disabled: true, 349 | list: [NeedsConfiguring], 350 | }); 351 | this.configure(); 352 | } 353 | }); 354 | } 355 | 356 | public render() { 357 | const multi =
358 | 361 | 362 |
363 | 364 | const single =
365 | 366 | {this.state.list.map((option: any) => )} 367 | 368 |
369 | 370 | return ( 371 | <> 372 | {this.state.multiselect ? multi : single} 373 | 374 | ); 375 | } 376 | } 377 | 378 | export default DataDrivenParameter; 379 | -------------------------------------------------------------------------------- /sandboxed/src/Selected.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { Button } from '@tableau/tableau-ui'; 3 | 4 | export interface SelectedProps { 5 | nextConfig?: boolean; 6 | onClear: () => void; 7 | selected: string; 8 | selecting: string; 9 | } 10 | 11 | // An individual setting that has been set 12 | export const Selected: React.SFC = (props) => { 13 | return ( 14 |
15 |

The {props.selecting} {props.selected} has been selected

16 | 17 |
18 | ); 19 | }; 20 | 21 | Selected.displayName = 'Selected'; 22 | -------------------------------------------------------------------------------- /sandboxed/src/Selector.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { Button, ButtonProps, DropdownSelect, DropdownSelectProps } from '@tableau/tableau-ui'; 3 | 4 | export interface SelectorProps { 5 | enabled: boolean; 6 | list: string[]; 7 | onChange: (e: React.ChangeEvent) => void; 8 | onClick: () => void; 9 | selected: string; 10 | } 11 | 12 | // Shows if setting has not yet been configured 13 | export const Selector: React.SFC = (props) => { 14 | const dropdownSelectProps: DropdownSelectProps = { 15 | className: 'dropdown-select', 16 | disabled: !props.enabled, 17 | kind: 'line', 18 | onChange: props.onChange, 19 | onSelect: props.onChange, 20 | value: props.selected, 21 | }; 22 | 23 | const buttonProps: ButtonProps = { 24 | disabled: !props.enabled || props.selected === '', 25 | kind: 'filledGreen', 26 | onClick: props.onClick, 27 | style: { marginLeft: '12px' }, 28 | }; 29 | 30 | return ( 31 |
32 | 33 | {props.list.map(option => )} 34 | 35 | 36 |
37 | ); 38 | }; 39 | 40 | Selector.displayName = 'Selector'; 41 | -------------------------------------------------------------------------------- /sandboxed/src/Setting.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { Selected } from './Selected'; 3 | import { Selector } from './Selector'; 4 | 5 | export interface SettingProps { 6 | config: boolean; 7 | enabled: boolean; 8 | list: string[]; 9 | nextConfig?: boolean; 10 | onChange: (e: React.ChangeEvent) => void; 11 | onClear: () => void; 12 | onClick: () => void; 13 | selected: string; 14 | selecting: string; 15 | } 16 | 17 | export const Setting: React.SFC = (props) => { 18 | return ( 19 | 20 | Select a {props.selecting} 21 | {renderSelectElement(props)} 22 | 23 | ); 24 | }; 25 | 26 | Setting.displayName = 'Setting'; 27 | 28 | function renderSelectElement(props: SettingProps): JSX.Element { 29 | const { config, enabled, list, nextConfig, onChange, onClear, onClick, selected, selecting } = props; 30 | 31 | return config ? : 32 | ; 33 | } 34 | -------------------------------------------------------------------------------- /sandboxed/src/entry_config.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import * as ReactDOM from 'react-dom'; 3 | import Configure from './Configure'; 4 | 5 | declare global { 6 | interface Window { tableau: any; } 7 | } 8 | 9 | ReactDOM.render(, document.getElementById('container')); 10 | -------------------------------------------------------------------------------- /sandboxed/src/entry_index.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import * as ReactDOM from 'react-dom'; 3 | import DataDrivenParameter from './DataDrivenParameter'; 4 | 5 | declare global { 6 | interface Window { tableau: any; } 7 | } 8 | 9 | ReactDOM.render(, document.getElementById('container')); 10 | -------------------------------------------------------------------------------- /sandboxed/src/imgs/arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tableau/extension-data-driven-parameters/3a97c522fb3cf36bd389366ef7626066f679345f/sandboxed/src/imgs/arrow.png -------------------------------------------------------------------------------- /sandboxed/src/index.tsx: -------------------------------------------------------------------------------- 1 | export { } 2 | -------------------------------------------------------------------------------- /sandboxed/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /sandboxed/src/serviceWorker.ts: -------------------------------------------------------------------------------- 1 | // This optional code is used to register a service worker. 2 | // register() is not called by default. 3 | 4 | // This lets the app load faster on subsequent visits in production, and gives 5 | // it offline capabilities. However, it also means that developers (and users) 6 | // will only see deployed updates on subsequent visits to a page, after all the 7 | // existing tabs open on the page have been closed, since previously cached 8 | // resources are updated in the background. 9 | 10 | // To learn more about the benefits of this model and instructions on how to 11 | // opt-in, read https://bit.ly/CRA-PWA 12 | 13 | const isLocalhost = Boolean( 14 | window.location.hostname === 'localhost' || 15 | // [::1] is the IPv6 localhost address. 16 | window.location.hostname === '[::1]' || 17 | // 127.0.0.1/8 is considered localhost for IPv4. 18 | window.location.hostname.match( 19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 20 | ) 21 | ); 22 | 23 | type Config = { 24 | onSuccess?: (registration: ServiceWorkerRegistration) => void; 25 | onUpdate?: (registration: ServiceWorkerRegistration) => void; 26 | }; 27 | 28 | export function register(config?: Config) { 29 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 30 | // The URL constructor is available in all browsers that support SW. 31 | const publicUrl = new URL( 32 | (process as { env: { [key: string]: string } }).env.PUBLIC_URL, 33 | window.location.href 34 | ); 35 | if (publicUrl.origin !== window.location.origin) { 36 | // Our service worker won't work if PUBLIC_URL is on a different origin 37 | // from what our page is served on. This might happen if a CDN is used to 38 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 39 | return; 40 | } 41 | 42 | window.addEventListener('load', () => { 43 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 44 | 45 | if (isLocalhost) { 46 | // This is running on localhost. Let's check if a service worker still exists or not. 47 | checkValidServiceWorker(swUrl, config); 48 | 49 | // Add some additional logging to localhost, pointing developers to the 50 | // service worker/PWA documentation. 51 | navigator.serviceWorker.ready.then(() => { 52 | console.log( 53 | 'This web app is being served cache-first by a service ' + 54 | 'worker. To learn more, visit https://bit.ly/CRA-PWA' 55 | ); 56 | }); 57 | } else { 58 | // Is not localhost. Just register service worker 59 | registerValidSW(swUrl, config); 60 | } 61 | }); 62 | } 63 | } 64 | 65 | function registerValidSW(swUrl: string, config?: Config) { 66 | navigator.serviceWorker 67 | .register(swUrl) 68 | .then(registration => { 69 | registration.onupdatefound = () => { 70 | const installingWorker = registration.installing; 71 | if (installingWorker == null) { 72 | return; 73 | } 74 | installingWorker.onstatechange = () => { 75 | if (installingWorker.state === 'installed') { 76 | if (navigator.serviceWorker.controller) { 77 | // At this point, the updated precached content has been fetched, 78 | // but the previous service worker will still serve the older 79 | // content until all client tabs are closed. 80 | console.log( 81 | 'New content is available and will be used when all ' + 82 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' 83 | ); 84 | 85 | // Execute callback 86 | if (config && config.onUpdate) { 87 | config.onUpdate(registration); 88 | } 89 | } else { 90 | // At this point, everything has been precached. 91 | // It's the perfect time to display a 92 | // "Content is cached for offline use." message. 93 | console.log('Content is cached for offline use.'); 94 | 95 | // Execute callback 96 | if (config && config.onSuccess) { 97 | config.onSuccess(registration); 98 | } 99 | } 100 | } 101 | }; 102 | }; 103 | }) 104 | .catch(error => { 105 | console.error('Error during service worker registration:', error); 106 | }); 107 | } 108 | 109 | function checkValidServiceWorker(swUrl: string, config?: Config) { 110 | // Check if the service worker can be found. If it can't reload the page. 111 | fetch(swUrl) 112 | .then(response => { 113 | // Ensure service worker exists, and that we really are getting a JS file. 114 | const contentType = response.headers.get('content-type'); 115 | if ( 116 | response.status === 404 || 117 | (contentType != null && contentType.indexOf('javascript') === -1) 118 | ) { 119 | // No service worker found. Probably a different app. Reload the page. 120 | navigator.serviceWorker.ready.then(registration => { 121 | registration.unregister().then(() => { 122 | window.location.reload(); 123 | }); 124 | }); 125 | } else { 126 | // Service worker found. Proceed as normal. 127 | registerValidSW(swUrl, config); 128 | } 129 | }) 130 | .catch(() => { 131 | console.log( 132 | 'No internet connection found. App is running in offline mode.' 133 | ); 134 | }); 135 | } 136 | 137 | export function unregister() { 138 | if ('serviceWorker' in navigator) { 139 | navigator.serviceWorker.ready.then(registration => { 140 | registration.unregister(); 141 | }); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /sandboxed/src/style.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | margin: 0; 4 | padding: 0; 5 | font-family: 'Benton Sans', Arial, Helvetica, sans-serif; 6 | font-size: 12px; 7 | color: rgba(0, 0, 0, 0.8); 8 | box-sizing: border-box; 9 | height: 100%; 10 | width: 100%; 11 | overflow: hidden; 12 | } 13 | 14 | #container { 15 | height: 100%; 16 | width: 100%; 17 | } 18 | 19 | .container { 20 | display: flex; 21 | flex-direction: column; 22 | justify-content: space-between; 23 | height: 100%; 24 | } 25 | 26 | .content { 27 | margin-left: 6px; 28 | } 29 | 30 | .header { 31 | font-size: 16px; 32 | color: rgba(0, 0, 0, 0.8); 33 | padding: 12px 0px 12px 18px; 34 | display: flex; 35 | } 36 | 37 | .title { 38 | font-family: 'Benton Sans Medium', Arial, Helvetica, sans-serif; 39 | font-size: 12px; 40 | color: rgba(0, 0, 0, 0.8); 41 | margin: 30px 0px 18px 0px; 42 | } 43 | 44 | p { 45 | margin: 0; 46 | } 47 | 48 | .selector { 49 | display: flex; 50 | min-height: 26px; 51 | margin-bottom: 12px; 52 | } 53 | 54 | .selected { 55 | margin-left: 10px; 56 | min-height: 26px; 57 | display: flex; 58 | justify-content: space-between; 59 | align-items: center; 60 | margin-bottom: 12px; 61 | } 62 | 63 | .option { 64 | display: flex; 65 | align-items: center; 66 | margin-top: 12px; 67 | } 68 | 69 | .footer { 70 | display: flex; 71 | align-items: flex-end; 72 | margin: 0px 18px; 73 | } 74 | 75 | .btncluster { 76 | display: flex; 77 | justify-content: flex-end; 78 | width: 100%; 79 | margin-bottom: 12px; 80 | } 81 | 82 | .format { 83 | display: flex; 84 | margin-top: 12px; 85 | } 86 | 87 | .formattext { 88 | width: 130px; 89 | } 90 | 91 | input[type="color"] { 92 | /* background-color: #fff; */ 93 | padding: 0; 94 | margin-left: 6px; 95 | border: 1px solid #666666; 96 | box-shadow: none; 97 | width: 16px; 98 | height: 16px; 99 | border-radius: 50%; 100 | outline: 0; 101 | } 102 | 103 | ::-webkit-color-swatch { 104 | border: none; 105 | } 106 | 107 | .tooltip { 108 | position: relative; 109 | display: inline-block; 110 | margin-left: 5px; 111 | padding-top: 2px; 112 | } 113 | 114 | .tooltip .tooltiptext { 115 | visibility: hidden; 116 | border: 1px solid #D4D4D4; 117 | border-radius: 1px; 118 | background: #fff; 119 | font-size: 10px; 120 | padding: 8px; 121 | width: 200px; 122 | position: absolute; 123 | z-index: 1; 124 | right: -100px; 125 | top: 20px; 126 | } 127 | 128 | .tooltip:hover .tooltiptext { 129 | visibility: visible; 130 | } 131 | 132 | .tooltiptext ol { 133 | padding: 0px 8px; 134 | margin: 0px; 135 | } 136 | 137 | .tooltiptext li { 138 | margin-top: 8px; 139 | } 140 | 141 | .parameter { 142 | width: 100%; 143 | font-family: 'Benton Sans', Arial, Helvetica, sans-serif; 144 | font-size: 12px; 145 | padding-left:6px; 146 | border: solid 1px #CBCBCB; 147 | } 148 | 149 | .parameter option { 150 | padding: 2px 2px 1px; 151 | height: 20px; 152 | display:flex; 153 | align-items: center; 154 | } 155 | 156 | .singleParameter { 157 | width: 100%; 158 | min-height: 20px !important; 159 | } 160 | 161 | .dropdown-select { 162 | flex: 1; 163 | margin-left: 0; 164 | width: '100%'; 165 | } 166 | 167 | .delimiter-text-field > input { 168 | font-family: 'Benton Sans', Arial, Helvetica, sans-serif; 169 | padding-right: 0; 170 | text-align: center; 171 | } 172 | 173 | /* Internet Explorer 10+ */ 174 | select::-ms-expand { 175 | visibility: hidden; 176 | } -------------------------------------------------------------------------------- /sandboxed/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "module": "esnext", 16 | "moduleResolution": "node", 17 | "resolveJsonModule": true, 18 | "isolatedModules": true, 19 | "noEmit": true, 20 | "jsx": "preserve" 21 | }, 22 | "include": [ 23 | "src" 24 | ] 25 | } 26 | -------------------------------------------------------------------------------- /src/DataDrivenParameter.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import './style.css'; 3 | import { Button, DropdownSelect } from '@tableau/tableau-ui'; 4 | const tableau = window.tableau; 5 | 6 | let unregister = [() => { }, () => { }, () => { }, () => { }]; 7 | 8 | interface State { 9 | allLabel: string, 10 | applyButton: boolean, 11 | applyButtonLabel: string, 12 | bg: string, 13 | configured: boolean, 14 | currentVal: any[], 15 | disabled: boolean, 16 | firstInit: boolean, 17 | list: any[], 18 | multiselect: boolean, 19 | } 20 | 21 | const NeedsConfiguring: any = { value: 'Parameter needs configuration', displayValue: 'Parameter needs configuration' }; 22 | const Loading: any = { value: 'Loading...', displayValue: 'Loading...' }; 23 | 24 | function fakeWhiteOverlay(hex: string) { 25 | const rgb = hexToRgb(hex); 26 | if (rgb) { 27 | return `rgb(${Math.min(Math.floor(rgb.r / 2) + 127, 255)}, ${Math.min(Math.floor(rgb.g / 2) + 127, 255)}, ${Math.min(Math.floor(rgb.b / 2) + 127, 255)})`; 28 | } else { 29 | return '#ffffff'; 30 | } 31 | } 32 | 33 | function hexToRgb(hex: string) { 34 | const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); 35 | return result ? { 36 | b: parseInt(result[3], 16), 37 | g: parseInt(result[2], 16), 38 | r: parseInt(result[1], 16), 39 | } : null; 40 | } 41 | 42 | class DataDrivenParameter extends React.Component { 43 | public readonly state: State = { 44 | allLabel: 'Apply', 45 | applyButton: false, 46 | applyButtonLabel: '(All)', 47 | bg: '#ffffff', 48 | configured: false, 49 | currentVal: [Loading], 50 | disabled: true, 51 | firstInit: true, 52 | list: [Loading], 53 | multiselect: false, 54 | }; 55 | 56 | // Pops open the configure page 57 | public configure = (): void => { 58 | const popupUrl = `${window.location.origin}${process.env.PUBLIC_URL}/#/config`; 59 | const payload = ''; 60 | tableau.extensions.ui.displayDialogAsync(popupUrl, payload, { height: 610, width: 450 }).then((closePayload: string) => { 61 | this.setup(); 62 | }).catch((error: any) => { 63 | if (tableau.extensions.settings.get('configured') !== 'true') { 64 | this.setState({ 65 | currentVal: [NeedsConfiguring], 66 | disabled: true, 67 | list: [NeedsConfiguring], 68 | }); 69 | } 70 | switch (error.errorCode) { 71 | case tableau.ErrorCodes.DialogClosedByUser: 72 | console.log('Dialog was closed by user.'); 73 | break; 74 | default: 75 | console.error(error.message); 76 | } 77 | }); 78 | } 79 | 80 | // Locates the parameter to update 81 | public findParameter() { 82 | const settings = tableau.extensions.settings.getAll(); 83 | const dashboard = tableau.extensions.dashboardContent.dashboard; 84 | dashboard.findParameterAsync(settings.selParam).then((parameter: any) => { 85 | if (!parameter || parameter.allowableValues.type !== 'all') { 86 | this.setState({ 87 | currentVal: [NeedsConfiguring], 88 | disabled: true, 89 | list: [NeedsConfiguring], 90 | }); 91 | } else { 92 | this.getParamData(); 93 | this.resetListeners(); 94 | } 95 | }); 96 | } 97 | 98 | // Gets the values from the selected field 99 | public getParamData = (): void => { 100 | const settings = tableau.extensions.settings.getAll(); 101 | const dashboard = tableau.extensions.dashboardContent.dashboard; 102 | const worksheet = dashboard.worksheets.find((ws: any) => ws.name === settings.selWorksheet); 103 | if (!worksheet) { 104 | this.setState({ 105 | currentVal: [NeedsConfiguring], 106 | disabled: true, 107 | list: [NeedsConfiguring], 108 | }); 109 | } else { 110 | worksheet.getSummaryDataAsync({ ignoreSelection: settings.ignoreSelection === 'true' }).then((dataTable: any) => { 111 | this.populateParam(dataTable); 112 | }); 113 | } 114 | } 115 | 116 | // Pulls domain of selected field 117 | public populateParam(dataTable: any) { 118 | const settings = tableau.extensions.settings.getAll(); 119 | const field = dataTable.columns.find((column: any) => column.fieldName === settings.selField); 120 | this.setState({ 121 | currentVal: [Loading], 122 | disabled: true, 123 | list: [Loading], 124 | }); 125 | 126 | if (!field) { 127 | this.setState({ 128 | currentVal: [NeedsConfiguring], 129 | disabled: true, 130 | list: [NeedsConfiguring], 131 | }); 132 | } else { 133 | this.createList(field, dataTable); 134 | } 135 | } 136 | 137 | // Populate list with values from data source 138 | public createList(field: any, dataTable: any) { 139 | const settings = tableau.extensions.settings.getAll(); 140 | const displayField = dataTable.columns.find((column: any) => column.fieldName === settings.displayField); 141 | 142 | let list: any[] = []; 143 | for (const row of dataTable.data) { 144 | const value = settings.useFormattedValues === 'true' ? row[field.index].formattedValue : row[field.index].value; 145 | let displayValue = value; 146 | if (displayField && settings.showDisplayValues === 'true') { 147 | displayValue = row[displayField.index].formattedValue 148 | } 149 | list.push({ 150 | displayValue, 151 | value, 152 | }); 153 | } 154 | 155 | // Remove duplicates 156 | list = list.filter((item, index, array) => array.indexOf(array.find(i => i.value === item.value)) === index); 157 | 158 | if (settings.dataType && (settings.dataType === 'int' || settings.dataType === 'float')) { 159 | // Convert to numbers for correct sort 160 | list = list.map((item) => ({ value: Number(item.value), displayValue: item.displayValue })) 161 | // Sort according to settings (numerical) 162 | if (settings.sort && settings.sort === 'desc') { 163 | list.sort((a, b) => b.value - a.value); 164 | } else { 165 | list.sort((a, b) => a.value - b.value); 166 | } 167 | if (settings.dataType === 'float') { 168 | list = list.map((item) => ({ value: item.value.toLocaleString(tableau.extensions.environment.locale), displayValue: item.displayValue })); 169 | } 170 | } else { 171 | // Sort according to settings 172 | if (settings.sort && settings.sort === 'desc') { 173 | list.sort((a, b) => a.value < b.value ? 1 : -1); 174 | } else { 175 | list.sort((a, b) => a.value > b.value ? 1 : -1); 176 | } 177 | } 178 | 179 | // Add '(All)' according to settings 180 | if (settings.includeAllValue === 'true') { 181 | list.unshift({ value: this.state.allLabel, displayValue: this.state.allLabel }); 182 | } 183 | 184 | this.setState({ 185 | list, 186 | }, this.setCurrentValue); 187 | 188 | } 189 | 190 | // Determine whether to use current param value or first value of list based on settings 191 | public setCurrentValue = (): void => { 192 | const settings = tableau.extensions.settings.getAll(); 193 | const dashboard = tableau.extensions.dashboardContent.dashboard; 194 | const list = this.state.list; 195 | let currentVal: any[] = []; 196 | dashboard.findParameterAsync(settings.selParam).then((parameter: any) => { 197 | if ((this.state.firstInit && settings.autoUpdate === 'true')) { 198 | // Then push new values 199 | currentVal = [(settings.includeAllValue === 'true' ? list[1].value : list[0].value)]; 200 | } else { 201 | // Then match parameter value 202 | if (settings.multiselect === 'true') { 203 | const tablist = []; 204 | for (const value of parameter.currentValue.value.split(settings.delimiter)) { 205 | if (list.find((v: any) => v.value.toString() === value || v.value === value)) { 206 | tablist.push(value); 207 | } 208 | } 209 | currentVal = tablist; 210 | } else { 211 | if (list.find((v: any) => v.value.toString() === parameter.currentValue.value || v.value === parameter.currentValue.value)) { 212 | currentVal = [parameter.currentValue.value]; 213 | } 214 | } 215 | if (currentVal.length === 0) { 216 | // If no match, use first value 217 | currentVal = [(settings.includeAllValue === 'true' ? list[1].value : list[0].value)]; 218 | } 219 | } 220 | 221 | parameter.changeValueAsync(settings.multiselect ? currentVal.join(settings.delimiter) : currentVal.toString()).then(console.log); 222 | 223 | this.setState({ 224 | disabled: false, 225 | firstInit: false, 226 | currentVal 227 | }); 228 | }); 229 | } 230 | 231 | // Adds event listener to worksheet and parameter 232 | public async registerListeners() { 233 | const settings = tableau.extensions.settings.getAll(); 234 | const dashboard = tableau.extensions.dashboardContent.dashboard; 235 | const worksheet = dashboard.worksheets.find((ws: any) => ws.name === settings.selWorksheet); 236 | dashboard.findParameterAsync(settings.selParam).then((parameter: any) => { 237 | if (!worksheet || !parameter) { 238 | this.setState({ 239 | currentVal: [NeedsConfiguring], 240 | disabled: true, 241 | list: [NeedsConfiguring], 242 | }); 243 | } else { 244 | if (!settings.updateOnSelectionFix || settings.updateOnSelectionFix === 'true') { 245 | unregister[0] = worksheet.addEventListener(tableau.TableauEventType.FilterChanged, this.getParamData); 246 | unregister[1] = worksheet.addEventListener(tableau.TableauEventType.MarkSelectionChanged, this.getParamData); 247 | } 248 | if (settings.matchParam === 'true') { 249 | unregister[2] = parameter.addEventListener(tableau.TableauEventType.ParameterChanged, this.matchListener); 250 | } 251 | if (settings.listenParam === 'true') { 252 | dashboard.findParameterAsync(settings.listenParamName).then((updateParameter: any) => { 253 | unregister[3] = updateParameter.addEventListener(tableau.TableauEventType.ParameterChanged, this.getParamData); 254 | }) 255 | } 256 | } 257 | }); 258 | } 259 | 260 | public matchListener = (): void => { 261 | const settings = tableau.extensions.settings.getAll(); 262 | const dashboard = tableau.extensions.dashboardContent.dashboard; 263 | dashboard.findParameterAsync(settings.selParam).then((parameter: any) => { 264 | const currentVal = this.state.multiselect ? parameter.currentValue.value.split(settings.delimiter) : [parameter.currentValue.value]; 265 | this.setState({ 266 | currentVal, 267 | }); 268 | }); 269 | } 270 | 271 | public resetListeners() { 272 | for (let fn of unregister) { 273 | fn(); 274 | } 275 | this.registerListeners(); 276 | } 277 | 278 | // Updates the parameter based on selection in Data-Driven Parameter 279 | public updateParam = (e: any) => { 280 | const settings = tableau.extensions.settings.getAll(); 281 | const dashboard = tableau.extensions.dashboardContent.dashboard; 282 | const values: any = []; 283 | let newValue: any; 284 | for (const opt of e.target.options) { 285 | if (opt.selected) { 286 | values.push(opt.value); 287 | } 288 | } 289 | this.setState({ currentVal: values }); 290 | newValue = values.join(settings.delimiter); 291 | dashboard.findParameterAsync(settings.selParam).then((parameter: any) => { 292 | if (!parameter) { 293 | this.setState({ 294 | currentVal: [NeedsConfiguring], 295 | disabled: true, 296 | list: [NeedsConfiguring], 297 | }); 298 | } else { 299 | if (settings.applyButton === 'false') { 300 | parameter.changeValueAsync(newValue).then(console.log); 301 | } 302 | } 303 | 304 | if (settings.updateOnChange === 'true') { 305 | // Don't update list if on multi-select, ends up being confusing. 306 | if (!this.state.multiselect) { 307 | this.getParamData(); 308 | } 309 | } 310 | }); 311 | } 312 | 313 | public apply = (): void => { 314 | const settings = tableau.extensions.settings.getAll(); 315 | const dashboard = tableau.extensions.dashboardContent.dashboard; 316 | dashboard.findParameterAsync(settings.selParam).then((parameter: any) => { 317 | parameter.changeValueAsync(this.state.currentVal.join(settings.delimiter)).then(console.log); 318 | }); 319 | } 320 | 321 | public setup() { 322 | const settings = tableau.extensions.settings.getAll(); 323 | document.body.style.backgroundColor = settings.bg; 324 | document.body.style.color = settings.txt; 325 | this.setState({ 326 | allLabel: settings.allLabel || '(All)', 327 | applyButton: settings.applyButton === 'true' || false, 328 | applyButtonLabel: settings.applyButtonLabel || 'Apply', 329 | bg: (settings.bg ? fakeWhiteOverlay(settings.bg) : '#ffffff'), 330 | configured: true, 331 | multiselect: settings.multiselect === 'true' || false, 332 | }); 333 | this.findParameter(); 334 | } 335 | 336 | // Once we have mounted, we call to initialize 337 | public componentWillMount() { 338 | tableau.extensions.initializeAsync({ configure: this.configure }).then(() => { 339 | const settings = tableau.extensions.settings.getAll(); 340 | if (settings.configured === 'true') { 341 | this.setup(); 342 | } else { 343 | this.setState({ 344 | currentVal: [NeedsConfiguring], 345 | disabled: true, 346 | list: [NeedsConfiguring], 347 | }); 348 | this.configure(); 349 | } 350 | }); 351 | } 352 | 353 | public render() { 354 | const multi =
355 | 358 | 359 |
360 | 361 | const single =
362 | 363 | {this.state.list.map((option: any) => )} 364 | 365 |
366 | 367 | return ( 368 | <> 369 | {this.state.multiselect ? multi : single} 370 | 371 | ); 372 | } 373 | } 374 | 375 | export default DataDrivenParameter; 376 | -------------------------------------------------------------------------------- /src/Home.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import './home.css'; 3 | 4 | class Home extends React.Component { 5 | public render() { 6 | return ( 7 | 8 |
9 |
10 |
11 |

Data-Driven Parameters

12 | Automatically update your parameters based on your data! 13 |
14 |
15 |

What is it?

16 |

This extension allows you to add a parameter to a Tableau dashboard whose domain is based on your data. Added a new product line? No longer do you need to manually edit the parameter to update it, with this extension your parameter values 17 | update automatically!

18 |

Using the Extension

19 |
    20 |
  1. Create an open input (All) parameter with a data type matching the field you want to use to populate it.
  2. 21 |
  3. Drag in a new Extension object to your dashboard.
  4. 22 |
  5. Find the manifest (.trex) file you downloaded above.
  6. 23 |
  7. Select the parameter you created above for the extension to manipulate.
  8. 24 |
  9. Select the worksheet that holds the field you want to base your parameter on.
  10. 25 |
  11. Select the field you want to base your parameter on.
  12. 26 |
  13. Optional: Configure your text and background colors.
  14. 27 |
  15. Click 'OK'.
  16. 28 |
29 |

Note: You can add as many instances of this extension as you like!

30 |
31 | Get this extension and more in the Tableau Exchange. 32 | {/* View on GitHub */} 33 |
34 |
35 |
36 |
37 |
38 | ); 39 | } 40 | } 41 | 42 | export default Home; -------------------------------------------------------------------------------- /src/Selected.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { Button } from '@tableau/tableau-ui'; 3 | 4 | export interface SelectedProps { 5 | nextConfig?: boolean; 6 | onClear: () => void; 7 | selected: string; 8 | selecting: string; 9 | } 10 | 11 | // An individual setting that has been set 12 | export const Selected: React.SFC = (props) => { 13 | return ( 14 |
15 |

The {props.selecting} {props.selected} has been selected

16 | 17 |
18 | ); 19 | }; 20 | 21 | Selected.displayName = 'Selected'; 22 | -------------------------------------------------------------------------------- /src/Selector.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { Button, ButtonProps, DropdownSelect, DropdownSelectProps } from '@tableau/tableau-ui'; 3 | 4 | export interface SelectorProps { 5 | enabled: boolean; 6 | list: string[]; 7 | onChange: (e: React.ChangeEvent) => void; 8 | onClick: () => void; 9 | selected: string; 10 | } 11 | 12 | // Shows if setting has not yet been configured 13 | export const Selector: React.SFC = (props) => { 14 | const dropdownSelectProps: DropdownSelectProps = { 15 | className: 'dropdown-select', 16 | disabled: !props.enabled, 17 | kind: 'line', 18 | onChange: props.onChange, 19 | onSelect: props.onChange, 20 | value: props.selected, 21 | }; 22 | 23 | const buttonProps: ButtonProps = { 24 | disabled: !props.enabled || props.selected === '', 25 | kind: 'filledGreen', 26 | onClick: props.onClick, 27 | style: { marginLeft: '12px' }, 28 | }; 29 | 30 | return ( 31 |
32 | 33 | {props.list.map(option => )} 34 | 35 | 36 |
37 | ); 38 | }; 39 | 40 | Selector.displayName = 'Selector'; 41 | -------------------------------------------------------------------------------- /src/Setting.tsx: -------------------------------------------------------------------------------- 1 | import * as React from 'react'; 2 | import { Selected } from './Selected'; 3 | import { Selector } from './Selector'; 4 | 5 | export interface SettingProps { 6 | config: boolean; 7 | enabled: boolean; 8 | list: string[]; 9 | nextConfig?: boolean; 10 | onChange: (e: React.ChangeEvent) => void; 11 | onClear: () => void; 12 | onClick: () => void; 13 | selected: string; 14 | selecting: string; 15 | } 16 | 17 | export const Setting: React.SFC = (props) => { 18 | return ( 19 | 20 | Select a {props.selecting} 21 | {renderSelectElement(props)} 22 | 23 | ); 24 | }; 25 | 26 | Setting.displayName = 'Setting'; 27 | 28 | function renderSelectElement(props: SettingProps): JSX.Element { 29 | const { config, enabled, list, nextConfig, onChange, onClear, onClick, selected, selecting } = props; 30 | 31 | return config ? : 32 | ; 33 | } 34 | -------------------------------------------------------------------------------- /src/home.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | margin: 0; 4 | padding: 0; 5 | height: 100%; 6 | width: 100%; 7 | color: #585858; 8 | border: 0; 9 | } 10 | 11 | .icontainer { 12 | font-size: 18px; 13 | background: #FAFAFA; 14 | display: flex; 15 | justify-content: center; 16 | align-items: center; 17 | height: 100%; 18 | } 19 | 20 | .box { 21 | background: #ffffff; 22 | max-width: 1250px; 23 | margin: 20px; 24 | display: flex; 25 | box-shadow: 2px 4px 8px rgba(102, 162, 222, 0.15); 26 | } 27 | 28 | .left { 29 | background: linear-gradient(to bottom left, #02B3A4, #66A2DE); 30 | padding: 40px; 31 | width: 450px; 32 | color: #ffffff; 33 | display: flex; 34 | align-items: center; 35 | align-content: center; 36 | justify-content: flex-start; 37 | flex-wrap: wrap; 38 | font-size: 20px; 39 | font-family: 'Benton Sans', Arial, Helvetica, sans-serif; 40 | } 41 | 42 | .right { 43 | padding: 40px; 44 | display: flex; 45 | align-items: center; 46 | align-content: center; 47 | justify-content: flex-start; 48 | flex-wrap: wrap; 49 | } 50 | 51 | .iheader { 52 | font-size: 64px; 53 | font-family: 'Bookman Old Style', Arial, Helvetica, sans-serif; 54 | margin: 10px 0px; 55 | line-height: 54px; 56 | } 57 | 58 | .big { 59 | font-size: 28px; 60 | width: 100%; 61 | margin: 5px 0px; 62 | } 63 | 64 | a { 65 | color: #02B3A4; 66 | font-weight: bold; 67 | text-decoration: none; 68 | } 69 | 70 | a:hover { 71 | text-decoration: underline; 72 | } 73 | 74 | .gh { 75 | font-size: 16px; 76 | text-align: center; 77 | width: 100%; 78 | } -------------------------------------------------------------------------------- /src/imgs/arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tableau/extension-data-driven-parameters/3a97c522fb3cf36bd389366ef7626066f679345f/src/imgs/arrow.png -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | import 'react-app-polyfill/ie11'; 2 | import * as React from 'react'; 3 | import * as ReactDOM from 'react-dom'; 4 | import { HashRouter, Route } from 'react-router-dom'; 5 | import Configure from './Configure'; 6 | import DataDrivenParameter from './DataDrivenParameter'; 7 | import Home from './Home'; 8 | 9 | declare global { 10 | interface Window { tableau: any; } 11 | } 12 | 13 | const PrimaryLayout = () => ( 14 | 15 | 16 | 17 | 18 | 19 | ) 20 | 21 | class App extends React.Component { 22 | public render() { 23 | return ( 24 | 25 | 26 | 27 | ) 28 | } 29 | } 30 | 31 | ReactDOM.render(, document.getElementById('container')); 32 | -------------------------------------------------------------------------------- /src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /src/serviceWorker.ts: -------------------------------------------------------------------------------- 1 | // This optional code is used to register a service worker. 2 | // register() is not called by default. 3 | 4 | // This lets the app load faster on subsequent visits in production, and gives 5 | // it offline capabilities. However, it also means that developers (and users) 6 | // will only see deployed updates on subsequent visits to a page, after all the 7 | // existing tabs open on the page have been closed, since previously cached 8 | // resources are updated in the background. 9 | 10 | // To learn more about the benefits of this model and instructions on how to 11 | // opt-in, read https://bit.ly/CRA-PWA 12 | 13 | const isLocalhost = Boolean( 14 | window.location.hostname === 'localhost' || 15 | // [::1] is the IPv6 localhost address. 16 | window.location.hostname === '[::1]' || 17 | // 127.0.0.1/8 is considered localhost for IPv4. 18 | window.location.hostname.match( 19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 20 | ) 21 | ); 22 | 23 | type Config = { 24 | onSuccess?: (registration: ServiceWorkerRegistration) => void; 25 | onUpdate?: (registration: ServiceWorkerRegistration) => void; 26 | }; 27 | 28 | export function register(config?: Config) { 29 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 30 | // The URL constructor is available in all browsers that support SW. 31 | const publicUrl = new URL( 32 | (process as { env: { [key: string]: string } }).env.PUBLIC_URL, 33 | window.location.href 34 | ); 35 | if (publicUrl.origin !== window.location.origin) { 36 | // Our service worker won't work if PUBLIC_URL is on a different origin 37 | // from what our page is served on. This might happen if a CDN is used to 38 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 39 | return; 40 | } 41 | 42 | window.addEventListener('load', () => { 43 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 44 | 45 | if (isLocalhost) { 46 | // This is running on localhost. Let's check if a service worker still exists or not. 47 | checkValidServiceWorker(swUrl, config); 48 | 49 | // Add some additional logging to localhost, pointing developers to the 50 | // service worker/PWA documentation. 51 | navigator.serviceWorker.ready.then(() => { 52 | console.log( 53 | 'This web app is being served cache-first by a service ' + 54 | 'worker. To learn more, visit https://bit.ly/CRA-PWA' 55 | ); 56 | }); 57 | } else { 58 | // Is not localhost. Just register service worker 59 | registerValidSW(swUrl, config); 60 | } 61 | }); 62 | } 63 | } 64 | 65 | function registerValidSW(swUrl: string, config?: Config) { 66 | navigator.serviceWorker 67 | .register(swUrl) 68 | .then(registration => { 69 | registration.onupdatefound = () => { 70 | const installingWorker = registration.installing; 71 | if (installingWorker == null) { 72 | return; 73 | } 74 | installingWorker.onstatechange = () => { 75 | if (installingWorker.state === 'installed') { 76 | if (navigator.serviceWorker.controller) { 77 | // At this point, the updated precached content has been fetched, 78 | // but the previous service worker will still serve the older 79 | // content until all client tabs are closed. 80 | console.log( 81 | 'New content is available and will be used when all ' + 82 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' 83 | ); 84 | 85 | // Execute callback 86 | if (config && config.onUpdate) { 87 | config.onUpdate(registration); 88 | } 89 | } else { 90 | // At this point, everything has been precached. 91 | // It's the perfect time to display a 92 | // "Content is cached for offline use." message. 93 | console.log('Content is cached for offline use.'); 94 | 95 | // Execute callback 96 | if (config && config.onSuccess) { 97 | config.onSuccess(registration); 98 | } 99 | } 100 | } 101 | }; 102 | }; 103 | }) 104 | .catch(error => { 105 | console.error('Error during service worker registration:', error); 106 | }); 107 | } 108 | 109 | function checkValidServiceWorker(swUrl: string, config?: Config) { 110 | // Check if the service worker can be found. If it can't reload the page. 111 | fetch(swUrl) 112 | .then(response => { 113 | // Ensure service worker exists, and that we really are getting a JS file. 114 | const contentType = response.headers.get('content-type'); 115 | if ( 116 | response.status === 404 || 117 | (contentType != null && contentType.indexOf('javascript') === -1) 118 | ) { 119 | // No service worker found. Probably a different app. Reload the page. 120 | navigator.serviceWorker.ready.then(registration => { 121 | registration.unregister().then(() => { 122 | window.location.reload(); 123 | }); 124 | }); 125 | } else { 126 | // Service worker found. Proceed as normal. 127 | registerValidSW(swUrl, config); 128 | } 129 | }) 130 | .catch(() => { 131 | console.log( 132 | 'No internet connection found. App is running in offline mode.' 133 | ); 134 | }); 135 | } 136 | 137 | export function unregister() { 138 | if ('serviceWorker' in navigator) { 139 | navigator.serviceWorker.ready.then(registration => { 140 | registration.unregister(); 141 | }); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/style.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | margin: 0; 4 | padding: 0; 5 | font-family: 'Benton Sans', Arial, Helvetica, sans-serif; 6 | font-size: 12px; 7 | color: rgba(0, 0, 0, 0.8); 8 | box-sizing: border-box; 9 | height: 100%; 10 | width: 100%; 11 | overflow: hidden; 12 | } 13 | 14 | #container { 15 | height: 100%; 16 | width: 100%; 17 | } 18 | 19 | .container { 20 | display: flex; 21 | flex-direction: column; 22 | justify-content: space-between; 23 | height: 100%; 24 | } 25 | 26 | .content { 27 | margin-left: 6px; 28 | } 29 | 30 | .header { 31 | font-size: 16px; 32 | color: rgba(0, 0, 0, 0.8); 33 | padding: 12px 0px 12px 18px; 34 | display: flex; 35 | } 36 | 37 | .title { 38 | font-family: 'Benton Sans Medium', Arial, Helvetica, sans-serif; 39 | font-size: 12px; 40 | color: rgba(0, 0, 0, 0.8); 41 | margin: 30px 0px 18px 0px; 42 | } 43 | 44 | p { 45 | margin: 0; 46 | } 47 | 48 | .selector { 49 | display: flex; 50 | min-height: 26px; 51 | margin-bottom: 12px; 52 | } 53 | 54 | .selected { 55 | margin-left: 10px; 56 | min-height: 26px; 57 | display: flex; 58 | justify-content: space-between; 59 | align-items: center; 60 | margin-bottom: 12px; 61 | } 62 | 63 | .option { 64 | display: flex; 65 | align-items: center; 66 | margin-top: 12px; 67 | } 68 | 69 | .footer { 70 | display: flex; 71 | align-items: flex-end; 72 | margin: 0px 18px; 73 | } 74 | 75 | .btncluster { 76 | display: flex; 77 | justify-content: flex-end; 78 | width: 100%; 79 | margin-bottom: 12px; 80 | } 81 | 82 | .format { 83 | display: flex; 84 | margin-top: 12px; 85 | } 86 | 87 | .formattext { 88 | width: 130px; 89 | } 90 | 91 | input[type="color"] { 92 | /* background-color: #fff; */ 93 | padding: 0; 94 | margin-left: 6px; 95 | border: 1px solid #666666; 96 | box-shadow: none; 97 | width: 16px; 98 | height: 16px; 99 | border-radius: 50%; 100 | outline: 0; 101 | } 102 | 103 | ::-webkit-color-swatch { 104 | border: none; 105 | } 106 | 107 | .tooltip { 108 | position: relative; 109 | display: inline-block; 110 | margin-left: 5px; 111 | padding-top: 2px; 112 | } 113 | 114 | .tooltip .tooltiptext { 115 | visibility: hidden; 116 | border: 1px solid #D4D4D4; 117 | border-radius: 1px; 118 | background: #fff; 119 | font-size: 10px; 120 | padding: 8px; 121 | width: 200px; 122 | position: absolute; 123 | z-index: 1; 124 | right: -100px; 125 | top: 20px; 126 | } 127 | 128 | .tooltip:hover .tooltiptext { 129 | visibility: visible; 130 | } 131 | 132 | .tooltiptext ol { 133 | padding: 0px 8px; 134 | margin: 0px; 135 | } 136 | 137 | .tooltiptext li { 138 | margin-top: 8px; 139 | } 140 | 141 | .parameter { 142 | width: 100%; 143 | font-family: 'Benton Sans', Arial, Helvetica, sans-serif; 144 | font-size: 12px; 145 | padding-left:6px; 146 | border: solid 1px #CBCBCB; 147 | } 148 | 149 | .parameter option { 150 | padding: 2px 2px 1px; 151 | height: 20px; 152 | display:flex; 153 | align-items: center; 154 | } 155 | 156 | .singleParameter { 157 | width: 100%; 158 | min-height: 20px !important; 159 | } 160 | 161 | .dropdown-select { 162 | flex: 1; 163 | margin-left: 0; 164 | width: '100%'; 165 | } 166 | 167 | .delimiter-text-field > input { 168 | font-family: 'Benton Sans', Arial, Helvetica, sans-serif; 169 | padding-right: 0; 170 | text-align: center; 171 | } 172 | 173 | /* Internet Explorer 10+ */ 174 | select::-ms-expand { 175 | visibility: hidden; 176 | } -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": [ 5 | "dom", 6 | "dom.iterable", 7 | "esnext" 8 | ], 9 | "allowJs": true, 10 | "skipLibCheck": true, 11 | "esModuleInterop": true, 12 | "allowSyntheticDefaultImports": true, 13 | "strict": true, 14 | "forceConsistentCasingInFileNames": true, 15 | "module": "esnext", 16 | "moduleResolution": "node", 17 | "resolveJsonModule": true, 18 | "isolatedModules": true, 19 | "noEmit": true, 20 | "jsx": "preserve" 21 | }, 22 | "jsRules": { 23 | "no-console": false 24 | }, 25 | "include": [ 26 | "src" 27 | ] 28 | } 29 | --------------------------------------------------------------------------------