├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── question.md ├── PULL_REQUEST_TEMPLATE.md ├── issue_label_bot.yaml ├── move.yml └── semantic.yml ├── .gitignore ├── .npmrc ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── babel.config.js ├── commitlint.config.js ├── lerna.json ├── package.json ├── packages ├── superset-ui-legacy-plugin-chart-event-flow │ ├── README.md │ ├── package.json │ └── src │ │ ├── EventFlow.jsx │ │ ├── images │ │ ├── thumbnail.png │ │ └── thumbnailLarge.png │ │ ├── index.js │ │ └── transformProps.js ├── superset-ui-legacy-plugin-chart-word-cloud │ ├── README.md │ ├── package.json │ └── src │ │ ├── ReactWordCloud.js │ │ ├── WordCloud.js │ │ ├── images │ │ ├── thumbnail.png │ │ └── thumbnailLarge.png │ │ ├── index.js │ │ └── transformProps.js ├── superset-ui-plugin-chart-icicle-event │ ├── README.md │ ├── package.json │ ├── src │ │ ├── IcicleEventChart.tsx │ │ ├── IcicleEventNode.ts │ │ ├── IcicleEventViz.tsx │ │ ├── createMetadata.ts │ │ ├── images │ │ │ └── thumbnail.png │ │ ├── index.ts │ │ ├── transformProps.ts │ │ └── utils │ │ │ ├── IcicleEventTreeHelpers.ts │ │ │ └── RenderedIcicleAccessors.ts │ ├── test │ │ └── utils │ │ │ └── IcicleEventTreeHelpers.test.ts │ └── types │ │ └── external.d.ts ├── superset-ui-plugin-chart-table │ ├── README.md │ ├── package.json │ ├── src │ │ ├── Table.tsx │ │ ├── TableFormData.ts │ │ ├── buildQuery.ts │ │ ├── components │ │ │ └── HTMLRenderer.tsx │ │ ├── createMetadata.ts │ │ ├── getRenderer.tsx │ │ ├── images │ │ │ └── thumbnail.png │ │ ├── index.ts │ │ ├── legacy │ │ │ ├── index.ts │ │ │ └── transformProps.ts │ │ ├── processColumns.ts │ │ ├── processData.ts │ │ ├── processMetrics.ts │ │ ├── transformProps.ts │ │ └── types.ts │ ├── test │ │ ├── buildQuery.test.ts │ │ ├── processData.test.ts │ │ └── processMetrics.test.ts │ └── types │ │ └── external.d.ts └── superset-ui-plugins-demo │ ├── .storybook │ ├── addons.js │ ├── config.js │ ├── storybook.css │ └── webpack.config.js │ ├── README.md │ ├── package.json │ ├── storybook │ ├── shared │ │ ├── components │ │ │ ├── ErrorMessage.tsx │ │ │ ├── Expandable.tsx │ │ │ ├── VerifyCORS.tsx │ │ │ └── createQueryStory.tsx │ │ └── dummyDatasource.ts │ └── stories │ │ ├── index.js │ │ ├── legacy-plugin-chart-event-flow │ │ ├── Stories.jsx │ │ └── index.js │ │ ├── legacy-plugin-chart-word-cloud │ │ ├── Stories.tsx │ │ ├── data.js │ │ └── index.js │ │ └── plugin-chart-table │ │ ├── Stories.jsx │ │ ├── data.js │ │ ├── dataLegacy.js │ │ ├── generateData.js │ │ └── index.js │ ├── tsconfig.json │ └── yarn.lock ├── scripts ├── build.js ├── buildAssets.js └── setupJest.js └── yarn.lock /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/about-codeowners/ 2 | # for more info about CODEOWNERS file 3 | 4 | # It uses the same pattern rule for gitignore file 5 | # https://git-scm.com/docs/gitignore#_pattern_format 6 | 7 | # These owners will be the default owners for everything in 8 | # the repo. Unless a later match takes precedence, 9 | # these users/team will be requested for review 10 | # when someone opens a pull request. 11 | 12 | * @apache-superset/embeddable-charts-team 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of what the bug is. 9 | 10 | **To Reproduce** 11 | Steps to reproduce the behavior: 12 | 1. Go to '...' 13 | 2. Click on '....' 14 | 3. Scroll down to '....' 15 | 4. See error 16 | 17 | **Expected behavior** 18 | A clear and concise description of what you expected to happen. 19 | 20 | **Screenshots** 21 | If applicable, add screenshots to help explain your problem. 22 | 23 | **Environment (please complete the following information):** 24 | - superset-ui version: [e.g. v0.5.0] 25 | - Node version: `node -v` 26 | - npm version: `npm -v` 27 | 28 | **Additional context** 29 | Add any other context about the problem here. 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question 3 | about: Ask for help with something. 4 | 5 | --- 6 | 7 | Your question. 8 | - How do I xxx? 9 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 💔 Breaking Changes 2 | 3 | 🏆 Enhancements 4 | 5 | 📜 Documentation 6 | 7 | 🐛 Bug Fix 8 | 9 | 🏠 Internal 10 | -------------------------------------------------------------------------------- /.github/issue_label_bot.yaml: -------------------------------------------------------------------------------- 1 | label-alias: 2 | bug: '#bug' 3 | feature_request: '#enhancement' 4 | question: '#question' 5 | -------------------------------------------------------------------------------- /.github/move.yml: -------------------------------------------------------------------------------- 1 | 2 | # Configuration for Move Issues - https://github.com/dessant/move-issues 3 | 4 | # Delete the command comment when it contains no other content 5 | deleteCommand: true 6 | 7 | # Close the source issue after moving 8 | closeSourceIssue: true 9 | 10 | # Lock the source issue after moving 11 | lockSourceIssue: false 12 | 13 | # Mention issue and comment authors 14 | mentionAuthors: true 15 | 16 | # Preserve mentions in the issue content 17 | keepContentMentions: false 18 | 19 | # Move labels that also exist on the target repository 20 | moveLabels: true 21 | 22 | # Set custom aliases for targets 23 | # aliases: 24 | # r: repo 25 | # or: owner/repo 26 | 27 | # Repository to extend settings from 28 | # _extends: repo -------------------------------------------------------------------------------- /.github/semantic.yml: -------------------------------------------------------------------------------- 1 | # Always validate the PR title, and ignore the commits 2 | titleOnly: true 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.DS_Store 3 | 4 | # Logs 5 | logs/ 6 | *.log 7 | 8 | # Cache 9 | .bundle/ 10 | .happo/ 11 | .idea/ 12 | .next/ 13 | .cache 14 | .eslintcache 15 | .idea 16 | .npm 17 | .vscode 18 | .yarnclean 19 | 20 | # Directories 21 | build/ 22 | coverage/ 23 | dist/ 24 | esm/ 25 | lib/ 26 | public/ 27 | node_modules/ 28 | tmp/ 29 | 30 | # Custom 31 | *.map 32 | *.min.js 33 | test-changelog.md 34 | 35 | # Configs (provided by Nimbus) 36 | .babelrc 37 | .eslintignore 38 | .eslintrc.js 39 | .flowconfig 40 | .prettierignore 41 | jest.config.js 42 | prettier.config.js 43 | tsconfig.eslint.json 44 | tsconfig.json 45 | tsconfig.options.json 46 | *.tsbuildinfo 47 | webpack.config.js 48 | 49 | # Lock files, libs should not have lock files 50 | npm-shrinkwrap.json 51 | package-lock.json 52 | old-yarn.lock 53 | .*.swp 54 | _gh-pages -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - '10.15' 5 | 6 | cache: 7 | - npm: true 8 | - yarn: true 9 | 10 | matrix: 11 | fast_finish: true 12 | 13 | install: 14 | - npm install -g codecov 15 | - yarn install 16 | 17 | before_script: 18 | - yarn build 19 | 20 | script: 21 | - yarn test 22 | 23 | after_script: 24 | - codecov 25 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # [0.0.0-master](https://github.com/apache-superset/superset-ui-plugins/compare/v0.11.11...v0.0.0-master) (2019-12-05) 2 | 3 | 4 | 5 | ## [0.11.11](https://github.com/apache-superset/superset-ui-plugins/compare/v0.11.10...v0.11.11) (2019-12-05) 6 | 7 | 8 | ### Bug Fixes 9 | 10 | * apply margins in nvd3 ([#283](https://github.com/apache-superset/superset-ui-plugins/issues/283)) ([a5fd631](https://github.com/apache-superset/superset-ui-plugins/commit/a5fd63102eafc8420d223fb149d9d0dd5c2f399f)) 11 | * both the CSS and className were expecting true/false strings ([#286](https://github.com/apache-superset/superset-ui-plugins/issues/286)) ([bbf7895](https://github.com/apache-superset/superset-ui-plugins/commit/bbf78958a805f7d5711e7dfb3aeaae6c56f220ec)) 12 | * GH issue 8669 NVD3 tooltip overflow ([#278](https://github.com/apache-superset/superset-ui-plugins/issues/278)) ([8586cc9](https://github.com/apache-superset/superset-ui-plugins/commit/8586cc9440a822885a6122795ac08313d2f4b5a0)) 13 | * JS exception: Cannot read property "dispatch" of undefined ([#287](https://github.com/apache-superset/superset-ui-plugins/issues/287)) ([faebd10](https://github.com/apache-superset/superset-ui-plugins/commit/faebd100dcc38e9532e7e74b12e0ba9181b7aa64)) 14 | 15 | 16 | 17 | ## [0.11.10](https://github.com/apache-superset/superset-ui-plugins/compare/v0.11.9...v0.11.10) (2019-11-21) 18 | 19 | 20 | 21 | ## [0.11.9](https://github.com/apache-superset/superset-ui-plugins/compare/v0.11.8...v0.11.9) (2019-11-20) 22 | 23 | 24 | ### Bug Fixes 25 | 26 | * minor wordcloud update ([73e09f6](https://github.com/apache-superset/superset-ui-plugins/commit/73e09f62ec5edede80d4681707481009c81d6fb2)) 27 | * **legacy-plugin-chart-horizon:** horizon chart should scroll when overflowing ([#180](https://github.com/apache-superset/superset-ui-plugins/issues/180)) ([8a5e84a](https://github.com/apache-superset/superset-ui-plugins/commit/8a5e84a06341c5e2af754689e1899a9040619302)) 28 | 29 | 30 | ### Features 31 | 32 | * **plugin-chart-word-cloud:** convert word cloud to use encodable ([#258](https://github.com/apache-superset/superset-ui-plugins/issues/258)) ([9b14285](https://github.com/apache-superset/superset-ui-plugins/commit/9b142855bc459196ed9b97ddc523755c3ac8a9e6)) 33 | * add Liechtenstein to country map chart ([#263](https://github.com/apache-superset/superset-ui-plugins/issues/263)) ([61ab1a2](https://github.com/apache-superset/superset-ui-plugins/commit/61ab1a273cb4cc0cadcfd1b74835167efe45f121)) 34 | 35 | 36 | 37 | ## [0.11.8](https://github.com/apache-superset/superset-ui-plugins/compare/v0.11.7...v0.11.8) (2019-11-20) 38 | 39 | 40 | ### Features 41 | 42 | * **legacy-plugin-chart-country-map:** add Switzerland to country map chart ([#260](https://github.com/apache-superset/superset-ui-plugins/issues/260)) ([2fded8a](https://github.com/apache-superset/superset-ui-plugins/commit/2fded8a07fb03ba9ac56502d374375b7bb58adf1)) 43 | 44 | 45 | 46 | ## [0.11.7](https://github.com/apache-superset/superset-ui-plugins/compare/v0.11.6...v0.11.7) (2019-11-15) 47 | 48 | 49 | ### Bug Fixes 50 | 51 | * **table:** fix rendering boolean ([#256](https://github.com/apache-superset/superset-ui-plugins/issues/256)) ([05e1cae](https://github.com/apache-superset/superset-ui-plugins/commit/05e1caebe6e01e2743e3e6b8f2177893b3e1f1c6)) 52 | 53 | 54 | 55 | ## [0.11.6](https://github.com/apache-superset/superset-ui-plugins/compare/v0.11.5...v0.11.6) (2019-11-13) 56 | 57 | 58 | ### Bug Fixes 59 | 60 | * **table:** fix sorting, column width calculation, and text wrapping ([#253](https://github.com/apache-superset/superset-ui-plugins/issues/253)) ([4b5cb1c](https://github.com/apache-superset/superset-ui-plugins/commit/4b5cb1c9dbb7088003b1129634441930bd74d690)) 61 | 62 | 63 | ### Features 64 | 65 | * add india to country_map visualization ([#182](https://github.com/apache-superset/superset-ui-plugins/issues/182)) ([9d5b1c3](https://github.com/apache-superset/superset-ui-plugins/commit/9d5b1c376e661db6d66c5381408cdc8c2d216770)) 66 | * improve table performance ([#246](https://github.com/apache-superset/superset-ui-plugins/issues/246)) ([bc46902](https://github.com/apache-superset/superset-ui-plugins/commit/bc469029468858b011d34e6df5078f12a4b39782)) 67 | 68 | 69 | 70 | ## [0.11.5](https://github.com/apache-superset/superset-ui-plugins/compare/v0.11.4...v0.11.5) (2019-11-09) 71 | 72 | 73 | ### Bug Fixes 74 | 75 | * lint ([2a4ad8b](https://github.com/apache-superset/superset-ui-plugins/commit/2a4ad8b0590ae98ed1c7d5e8a3bfec2cb5cae5c8)) 76 | * lint ([0782719](https://github.com/apache-superset/superset-ui-plugins/commit/0782719fdd9a7ae43a85710c483e32dda55d3c1e)) 77 | * pass all props to transformProps in LineMulti chart ([#247](https://github.com/apache-superset/superset-ui-plugins/issues/247)) ([c80d8a9](https://github.com/apache-superset/superset-ui-plugins/commit/c80d8a98dbe6820be6e6b5e0cea4d60d5558ceb6)) 78 | 79 | 80 | 81 | ## [0.11.4](https://github.com/apache-superset/superset-ui-plugins/compare/v0.11.3...v0.11.4) (2019-10-31) 82 | 83 | 84 | ### Bug Fixes 85 | 86 | * **table:** fixed performance issue ([#241](https://github.com/apache-superset/superset-ui-plugins/issues/241)) ([dfdf263](https://github.com/apache-superset/superset-ui-plugins/commit/dfdf2636d35ec66b2fcd90f7e2df4cae2d998a65)) 87 | * change world map color scheme ([#215](https://github.com/apache-superset/superset-ui-plugins/issues/215)) ([f94a19b](https://github.com/apache-superset/superset-ui-plugins/commit/f94a19bab71ea2ccdbafc402b187b95b23f53533)) 88 | 89 | 90 | ### Features 91 | 92 | * add Korea(South) to Country Maps ([#230](https://github.com/apache-superset/superset-ui-plugins/issues/230)) ([1865bd5](https://github.com/apache-superset/superset-ui-plugins/commit/1865bd5783b826136bce99cd4ef7ae8505d9c748)) 93 | 94 | 95 | 96 | ## [0.11.3](https://github.com/apache-superset/superset-ui-plugins/compare/v0.11.2...v0.11.3) (2019-10-16) 97 | 98 | 99 | ### Bug Fixes 100 | 101 | * **table:** TableVis dynamic height enabled ([#229](https://github.com/apache-superset/superset-ui-plugins/issues/229)) ([f4f1a85](https://github.com/apache-superset/superset-ui-plugins/commit/f4f1a8565134d322a163c14d32e5fb3831a20a34)), closes [#233](https://github.com/apache-superset/superset-ui-plugins/issues/233) 102 | * add typings for @storybook/react ([#203](https://github.com/apache-superset/superset-ui-plugins/issues/203)) ([6aef8ee](https://github.com/apache-superset/superset-ui-plugins/commit/6aef8ee38883f44f3d69c2120cfc3f1858d7bfe4)) 103 | * Line not hidden after legend selection ([#204](https://github.com/apache-superset/superset-ui-plugins/issues/204)) ([484d639](https://github.com/apache-superset/superset-ui-plugins/commit/484d63993b81d593183f1f1a2b8f9d91aeef310f)) 104 | 105 | 106 | 107 | ## [0.11.2](https://github.com/apache-superset/superset-ui-plugins/compare/v0.11.1...v0.11.2) (2019-09-12) 108 | 109 | 110 | ### Bug Fixes 111 | 112 | * **datatable:** adding the consideration of padding ([#198](https://github.com/apache-superset/superset-ui-plugins/issues/198)) ([0f93850](https://github.com/apache-superset/superset-ui-plugins/commit/0f93850f294a9682a4e792218215c6109a14b862)) 113 | 114 | 115 | ### Features 116 | 117 | * **datatable:** render html correctly ([#199](https://github.com/apache-superset/superset-ui-plugins/issues/199)) ([170ba7c](https://github.com/apache-superset/superset-ui-plugins/commit/170ba7cf9de1a450c60aa78022be28f6c63922ea)) 118 | 119 | 120 | 121 | ## [0.11.1](https://github.com/apache-superset/superset-ui-plugins/compare/v0.11.0...v0.11.1) (2019-09-11) 122 | 123 | 124 | ### Bug Fixes 125 | 126 | * remove redundant target from sankey tooltip ([#193](https://github.com/apache-superset/superset-ui-plugins/issues/193)) ([3eed662](https://github.com/apache-superset/superset-ui-plugins/commit/3eed66287a620080d5e10c39e1713143d88904c7)) 127 | * **tablevis:** Set proper width for each column ([#189](https://github.com/apache-superset/superset-ui-plugins/issues/189)) ([4cab838](https://github.com/apache-superset/superset-ui-plugins/commit/4cab8387b15ff4fcaa5df23eb09c70bffdf9daad)) 128 | 129 | 130 | 131 | # [0.11.0](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.46...v0.11.0) (2019-08-26) 132 | 133 | 134 | ### Features 135 | 136 | * upgrade [@superset-ui](https://github.com/superset-ui) to v0.12 ([#183](https://github.com/apache-superset/superset-ui-plugins/issues/183)) ([74d75f2](https://github.com/apache-superset/superset-ui-plugins/commit/74d75f2654f5363638479833c891686bc57947b1)) 137 | 138 | 139 | 140 | ## [0.10.46](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.45...v0.10.46) (2019-08-21) 141 | 142 | 143 | ### Bug Fixes 144 | 145 | * **force to publish new version:** force to publish new version ([e27fbe6](https://github.com/apache-superset/superset-ui-plugins/commit/e27fbe693e8a11befadac33d9d3f89b74ce99f86)) 146 | 147 | 148 | 149 | ## [0.10.45](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.44...v0.10.45) (2019-08-21) 150 | 151 | 152 | ### Bug Fixes 153 | 154 | * **fix issues in superset:** fix issues in superset ([838bb43](https://github.com/apache-superset/superset-ui-plugins/commit/838bb430025bb951fbef534e6a04b7a4e1f1ba39)) 155 | 156 | 157 | 158 | ## [0.10.44](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.43...v0.10.44) (2019-08-15) 159 | 160 | 161 | ### Bug Fixes 162 | 163 | * move react to table peerdependency ([#179](https://github.com/apache-superset/superset-ui-plugins/issues/179)) ([dde7037](https://github.com/apache-superset/superset-ui-plugins/commit/dde7037451a0ace4fa0b462334e6dae707302311)) 164 | 165 | 166 | 167 | ## [0.10.43](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.42...v0.10.43) (2019-08-15) 168 | 169 | 170 | 171 | ## [0.10.42](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.41...v0.10.42) (2019-08-15) 172 | 173 | 174 | ### Bug Fixes 175 | 176 | * **fix types:** fix types ([a42d014](https://github.com/apache-superset/superset-ui-plugins/commit/a42d014ca8d514db8aea11cac5126a3dbc973e7c)) 177 | * **tablevis:** update datatable change ([fb746d8](https://github.com/apache-superset/superset-ui-plugins/commit/fb746d8547b1890887657183f8155f7f6e0107e0)) 178 | 179 | 180 | 181 | ## [0.10.41](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.40...v0.10.41) (2019-08-13) 182 | 183 | 184 | ### Bug Fixes 185 | 186 | * **adjusted upstream break change:** adjusted upstream break change ([244eca8](https://github.com/apache-superset/superset-ui-plugins/commit/244eca8b9b36eaf089c6ef8e67e6c942cebd6486)) 187 | * **bump lunar version of datatable:** bump lunar version of datatable ([49c7448](https://github.com/apache-superset/superset-ui-plugins/commit/49c744883d9336444e5871c0b30429e0121f6283)) 188 | * **memorize filter in state:** memorize filter in state ([893320a](https://github.com/apache-superset/superset-ui-plugins/commit/893320a9904f0b3400816e100efc9dc75e370e05)) 189 | 190 | 191 | ### Features 192 | 193 | * update type for line chart series ([#175](https://github.com/apache-superset/superset-ui-plugins/issues/175)) ([c920d55](https://github.com/apache-superset/superset-ui-plugins/commit/c920d55b8eddf64e2929ae006f88f969fc3aaf11)) 194 | * **added search bar:** added search bar ([861e3db](https://github.com/apache-superset/superset-ui-plugins/commit/861e3dbe09db33cd2015e41e20c9efb9b371179a)) 195 | * **code refactoring:** code refactoring ([c5e51b6](https://github.com/apache-superset/superset-ui-plugins/commit/c5e51b6227f9694b92431894b0d83fec93ada1c8)) 196 | * simply the data processing logic ([31faede](https://github.com/apache-superset/superset-ui-plugins/commit/31faede5882c42b8a19e0ea9306c1cfad7c06bd2)) 197 | * **remove unused package:** remove corejs and other unused package ([04b7cd0](https://github.com/apache-superset/superset-ui-plugins/commit/04b7cd08ee773babf4577d4463aea48d3955f194)) 198 | * **tablevis:** this pr is to add a new tablevis plguin to the system ([dd0f916](https://github.com/apache-superset/superset-ui-plugins/commit/dd0f9168d7e38f2e0c3264d78eaff018ad587c21)) 199 | 200 | 201 | 202 | ## [0.10.40](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.39...v0.10.40) (2019-08-08) 203 | 204 | 205 | ### Features 206 | 207 | * add basic functionality for icicle chart to display static data ([#165](https://github.com/apache-superset/superset-ui-plugins/issues/165)) ([895758b](https://github.com/apache-superset/superset-ui-plugins/commit/895758b12350727e4b0dbcd5b5a39ec389c5cd22)) 208 | 209 | 210 | 211 | ## [0.10.39](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.38...v0.10.39) (2019-08-06) 212 | 213 | 214 | ### Bug Fixes 215 | 216 | * only remove tooltips relating to a single vis ([#167](https://github.com/apache-superset/superset-ui-plugins/issues/167)) ([8059485](https://github.com/apache-superset/superset-ui-plugins/commit/8059485d2bd93cf15609d7dd2ae896706b1caf73)) 217 | 218 | 219 | ### Features 220 | 221 | * file skeleton necessary for icicle chart visualization ([#162](https://github.com/apache-superset/superset-ui-plugins/issues/162)) ([ecd5744](https://github.com/apache-superset/superset-ui-plugins/commit/ecd5744481c6a13ca381dcd84eed17a98f180e5d)) 222 | 223 | 224 | 225 | ## [0.10.38](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.37...v0.10.38) (2019-07-29) 226 | 227 | 228 | ### Bug Fixes 229 | 230 | * nvd3 charts break on stateChange dispatch ([#159](https://github.com/apache-superset/superset-ui-plugins/issues/159)) ([bd1245d](https://github.com/apache-superset/superset-ui-plugins/commit/bd1245d83d211c8dd65287d3123a92dc05765e2c)) 231 | 232 | 233 | 234 | ## [0.10.37](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.36...v0.10.37) (2019-07-26) 235 | 236 | 237 | ### Bug Fixes 238 | 239 | * disable lint error ([#150](https://github.com/apache-superset/superset-ui-plugins/issues/150)) ([d770a14](https://github.com/apache-superset/superset-ui-plugins/commit/d770a140e4ba4c3e59bf25a5e2a0edb7b2b3b9aa)) 240 | * single y axis bounds ([#148](https://github.com/apache-superset/superset-ui-plugins/issues/148)) ([49da856](https://github.com/apache-superset/superset-ui-plugins/commit/49da856945cde9e3dd762c52062d0d1dd4362c08)) 241 | 242 | 243 | 244 | ## [0.10.36](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.35...v0.10.36) (2019-07-22) 245 | 246 | 247 | ### Bug Fixes 248 | 249 | * responsive y-axis on stacked charts ([#141](https://github.com/apache-superset/superset-ui-plugins/issues/141)) ([8f60a5d](https://github.com/apache-superset/superset-ui-plugins/commit/8f60a5d4f991f9de05c4e7a66b4e6a2adcbd7e93)) 250 | 251 | 252 | 253 | ## [0.10.35](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.34...v0.10.35) (2019-07-08) 254 | 255 | 256 | ### Bug Fixes 257 | 258 | * fixing tooltip for expanded area chart ([#134](https://github.com/apache-superset/superset-ui-plugins/issues/134)) ([6a4986e](https://github.com/apache-superset/superset-ui-plugins/commit/6a4986edf28e6f6a2cc4ed18d5defe276a6b04c4)) 259 | 260 | 261 | 262 | ## [0.10.34](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.33...v0.10.34) (2019-06-26) 263 | 264 | 265 | 266 | ## [0.10.33](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.32...v0.10.33) (2019-06-26) 267 | 268 | 269 | ### Bug Fixes 270 | 271 | * heatmap errors with null data ([3206645](https://github.com/apache-superset/superset-ui-plugins/commit/3206645a613df0b741c1c06c6084e28b7cc9d607)) 272 | 273 | 274 | 275 | ## [0.10.32](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.31...v0.10.32) (2019-06-12) 276 | 277 | 278 | ### Bug Fixes 279 | 280 | * ignore disabled series in stacked bar values ([#116](https://github.com/apache-superset/superset-ui-plugins/issues/116)) ([da8390e](https://github.com/apache-superset/superset-ui-plugins/commit/da8390ea747a39ecf1b28ea92423b782e912a2b8)) 281 | 282 | 283 | 284 | ## [0.10.31](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.30...v0.10.31) (2019-06-06) 285 | 286 | 287 | ### Bug Fixes 288 | 289 | * legend types ([b704671](https://github.com/apache-superset/superset-ui-plugins/commit/b7046716551a53faebe1b4b241210cb0e16a4933)) 290 | * move series in front of xy gridlines ([#119](https://github.com/apache-superset/superset-ui-plugins/issues/119)) ([0042f46](https://github.com/apache-superset/superset-ui-plugins/commit/0042f4609899f1009d69c5eb732291834dd92010)) 291 | 292 | 293 | ### Features 294 | 295 | * add getDomain to ChannelEncoder ([e2ea8c8](https://github.com/apache-superset/superset-ui-plugins/commit/e2ea8c80fc3283e0e184dfe85b6e8645e74a7ac9)) 296 | * channels can take array of definitions ([e105629](https://github.com/apache-superset/superset-ui-plugins/commit/e10562942700050a7c510aa1ac52e3f540366777)) 297 | * create reusable selector factory for Encoder ([c208272](https://github.com/apache-superset/superset-ui-plugins/commit/c20827219f70f4d8a0ff7b66a0b1efda5df2a850)) 298 | * remove children from XYChartLayout parameter ([cd74445](https://github.com/apache-superset/superset-ui-plugins/commit/cd7444509aedeb640ba321bae278e798ac370fa3)) 299 | * simplify Encoder creation ([5d20d82](https://github.com/apache-superset/superset-ui-plugins/commit/5d20d821f140e3fddf9d9f52ce5928cf9304efed)) 300 | 301 | 302 | 303 | ## [0.10.30](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.29...v0.10.30) (2019-06-02) 304 | 305 | 306 | ### Bug Fixes 307 | 308 | * **preset-chart-xy:** Pick LegendRenderer ([#118](https://github.com/apache-superset/superset-ui-plugins/issues/118)) ([92373c2](https://github.com/apache-superset/superset-ui-plugins/commit/92373c2e191bcdb7a31e4952b1d2c039b03a5bbc)) 309 | 310 | 311 | 312 | ## [0.10.29](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.28...v0.10.29) (2019-05-31) 313 | 314 | 315 | ### Bug Fixes 316 | 317 | * scale type category missing ordinal ([1516ed4](https://github.com/apache-superset/superset-ui-plugins/commit/1516ed49bb7c2f6fa4c39e87f8e4041309727aac)) 318 | 319 | 320 | 321 | ## [0.10.28](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.27...v0.10.28) (2019-05-31) 322 | 323 | 324 | ### Bug Fixes 325 | 326 | * lint ([ad4a3c4](https://github.com/apache-superset/superset-ui-plugins/commit/ad4a3c4aedf1e1aa42e2c2b8ba17e63b44d5b13e)) 327 | 328 | 329 | ### Features 330 | 331 | * implement labelFlush behavior for continuous axes ([#117](https://github.com/apache-superset/superset-ui-plugins/issues/117)) ([80b2227](https://github.com/apache-superset/superset-ui-plugins/commit/80b2227d8012a0de6b6d024db439ab9faa58cd93)) 332 | 333 | 334 | 335 | ## [0.10.27](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.26...v0.10.27) (2019-05-30) 336 | 337 | 338 | ### Bug Fixes 339 | 340 | * convert scale config to data-ui's config correctly ([#115](https://github.com/apache-superset/superset-ui-plugins/issues/115)) ([f37f2dd](https://github.com/apache-superset/superset-ui-plugins/commit/f37f2dd6433c24fb185609a71929807716aea3f5)) 341 | 342 | 343 | 344 | ## [0.10.26](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.25...v0.10.26) (2019-05-30) 345 | 346 | 347 | ### Bug Fixes 348 | 349 | * move padding ([f52e48a](https://github.com/apache-superset/superset-ui-plugins/commit/f52e48a44f9b43720640a573468c2efb00e1eecf)) 350 | 351 | 352 | 353 | ## [0.10.25](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.24...v0.10.25) (2019-05-25) 354 | 355 | 356 | 357 | ## [0.10.24](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.23...v0.10.24) (2019-05-24) 358 | 359 | 360 | ### Features 361 | 362 | * allow boolean as axis config ([e996d24](https://github.com/apache-superset/superset-ui-plugins/commit/e996d24050bd530654a69fe5230355a7b9d2b6c5)) 363 | 364 | 365 | 366 | ## [0.10.23](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.22...v0.10.23) (2019-05-21) 367 | 368 | 369 | ### Bug Fixes 370 | 371 | * gridlines ([961a0c6](https://github.com/apache-superset/superset-ui-plugins/commit/961a0c6a7e3be422ba6e2a5d7bfab988451dfe85)) 372 | 373 | 374 | ### Features 375 | 376 | * support custom tooltip for scatterplot and box plot ([fbf6be3](https://github.com/apache-superset/superset-ui-plugins/commit/fbf6be3f6bf7c3591c21afb6cb3980d73f8a7a1e)) 377 | * support line strokeWidth ([#105](https://github.com/apache-superset/superset-ui-plugins/issues/105)) ([45bdfbb](https://github.com/apache-superset/superset-ui-plugins/commit/45bdfbb353c37f7a7da687453c64de9019ec9447)) 378 | 379 | 380 | 381 | ## [0.10.22](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.21...v0.10.22) (2019-05-17) 382 | 383 | 384 | 385 | ## [0.10.21](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.20...v0.10.21) (2019-05-17) 386 | 387 | 388 | ### Features 389 | 390 | * add types to published list ([0f4614f](https://github.com/apache-superset/superset-ui-plugins/commit/0f4614f4fed44569aa426ad5e292b6953ba8048d)) 391 | 392 | 393 | 394 | ## [0.10.20](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.19...v0.10.20) (2019-05-17) 395 | 396 | 397 | 398 | ## [0.10.19](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.18...v0.10.19) (2019-05-17) 399 | 400 | 401 | ### Bug Fixes 402 | 403 | * invalid margin breaking chart ([#102](https://github.com/apache-superset/superset-ui-plugins/issues/102)) ([dc874b0](https://github.com/apache-superset/superset-ui-plugins/commit/dc874b0d3a50feb19759e1b4001dfdb7ff0b15bb)) 404 | 405 | 406 | 407 | ## [0.10.18](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.17...v0.10.18) (2019-05-16) 408 | 409 | 410 | ### Features 411 | 412 | * support tooltip and legend overrides ([#101](https://github.com/apache-superset/superset-ui-plugins/issues/101)) ([a803786](https://github.com/apache-superset/superset-ui-plugins/commit/a8037869072a2ebfb011cab6aac9a3f57248a367)) 413 | 414 | 415 | 416 | ## [0.10.17](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.16...v0.10.17) (2019-05-14) 417 | 418 | 419 | ### Bug Fixes 420 | 421 | * disable lazy import for line chart and box plot ([#82](https://github.com/apache-superset/superset-ui-plugins/issues/82)) ([5161e5e](https://github.com/apache-superset/superset-ui-plugins/commit/5161e5ee08506f98a0a0e52915a1624bca0bb65e)) 422 | * lint ([#79](https://github.com/apache-superset/superset-ui-plugins/issues/79)) ([7a89ae8](https://github.com/apache-superset/superset-ui-plugins/commit/7a89ae8994cf238542d8430045d584070caa41ec)) 423 | 424 | 425 | ### Features 426 | 427 | * add box plot ([#78](https://github.com/apache-superset/superset-ui-plugins/issues/78)) ([72d4c30](https://github.com/apache-superset/superset-ui-plugins/commit/72d4c30d3bb2455a95af03fa4f4d3b9cc8fa2f31)) 428 | * add scatter plot ([#90](https://github.com/apache-superset/superset-ui-plugins/issues/90)) ([cf07d9d](https://github.com/apache-superset/superset-ui-plugins/commit/cf07d9d5a81ef5a296ceaf82cee5892f4fd0062d)) 429 | * allow legend overrides at multiple levels ([#81](https://github.com/apache-superset/superset-ui-plugins/issues/81)) ([067f29b](https://github.com/apache-superset/superset-ui-plugins/commit/067f29b524aa28cdad44ff041f5e61eb2907281d)) 430 | * bring lazy import back ([#84](https://github.com/apache-superset/superset-ui-plugins/issues/84)) ([72c0203](https://github.com/apache-superset/superset-ui-plugins/commit/72c020319dfdcfd0e8a69d93c3318ca085465de0)) 431 | 432 | 433 | 434 | ## [0.10.16](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.15...v0.10.16) (2019-05-03) 435 | 436 | 437 | ### Features 438 | 439 | * add sankey chart with loops ([#77](https://github.com/apache-superset/superset-ui-plugins/issues/77)) ([e2d5191](https://github.com/apache-superset/superset-ui-plugins/commit/e2d5191523d83547a0ebfc2537ab984852eb8649)) 440 | 441 | 442 | 443 | ## [0.10.15](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.14...v0.10.15) (2019-04-27) 444 | 445 | 446 | ### Bug Fixes 447 | 448 | * rename file from js to ts ([#75](https://github.com/apache-superset/superset-ui-plugins/issues/75)) ([c4c7b6d](https://github.com/apache-superset/superset-ui-plugins/commit/c4c7b6d89cd94c95ea26f84b9b62ee381e65f1e5)) 449 | 450 | 451 | 452 | ## [0.10.14](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.13...v0.10.14) (2019-04-26) 453 | 454 | 455 | ### Bug Fixes 456 | 457 | * lazily create metadata ([#74](https://github.com/apache-superset/superset-ui-plugins/issues/74)) ([2fef425](https://github.com/apache-superset/superset-ui-plugins/commit/2fef425c90bf40a8c86c9fb7e0f2a48affc36962)) 458 | 459 | 460 | ### Features 461 | 462 | * bump dependencies ([3f34865](https://github.com/apache-superset/superset-ui-plugins/commit/3f34865afb323651d47eaef86a098a6dc3e66d87)) 463 | 464 | 465 | 466 | ## [0.10.13](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.12...v0.10.13) (2019-04-26) 467 | 468 | 469 | ### Bug Fixes 470 | 471 | * make line chart query operate in time series mode ([#71](https://github.com/apache-superset/superset-ui-plugins/issues/71)) ([4d9a479](https://github.com/apache-superset/superset-ui-plugins/commit/4d9a479a68131b95163ff924be4f414078954f3c)) 472 | 473 | 474 | ### Features 475 | 476 | * integrate line chart with build query and update typings ([#73](https://github.com/apache-superset/superset-ui-plugins/issues/73)) ([311d607](https://github.com/apache-superset/superset-ui-plugins/commit/311d60713f94cef529bdd09bcb81e916b6c81f49)) 477 | * update data format returned from query api and add getGroupBys ([#72](https://github.com/apache-superset/superset-ui-plugins/issues/72)) ([3bbedb2](https://github.com/apache-superset/superset-ui-plugins/commit/3bbedb2a0aadb77e22958371703ced2a5875a6da)) 478 | 479 | 480 | 481 | ## [0.10.12](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.11...v0.10.12) (2019-04-24) 482 | 483 | 484 | ### Bug Fixes 485 | 486 | * line chart does not handle temporal field correctly ([#68](https://github.com/apache-superset/superset-ui-plugins/issues/68)) ([79ff3e1](https://github.com/apache-superset/superset-ui-plugins/commit/79ff3e15e70356700464334a98643f96c33b754a)) 487 | * word cloud import bug ([#65](https://github.com/apache-superset/superset-ui-plugins/issues/65)) ([dafdc0b](https://github.com/apache-superset/superset-ui-plugins/commit/dafdc0bafe5a29cbda3edc1259e3922d3284de02)) 488 | 489 | 490 | ### Features 491 | 492 | * adding Canada into the list of country map choices ([#48](https://github.com/apache-superset/superset-ui-plugins/issues/48)) ([eb9ffb5](https://github.com/apache-superset/superset-ui-plugins/commit/eb9ffb50ea4eea166d02f61f6928505942098955)) 493 | * improve line chart margin/axis and add buildquery ([#66](https://github.com/apache-superset/superset-ui-plugins/issues/66)) ([9c9dd9d](https://github.com/apache-superset/superset-ui-plugins/commit/9c9dd9d4c6fb15358741fee2a05938bfc4b45ef4)) 494 | * update line chart thumbnail and scale extraction ([#61](https://github.com/apache-superset/superset-ui-plugins/issues/61)) ([69a405c](https://github.com/apache-superset/superset-ui-plugins/commit/69a405c52a1237ae6bc31f55ed65a522312ed36a)) 495 | 496 | 497 | 498 | ## [0.10.11](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.10...v0.10.11) (2019-04-12) 499 | 500 | 501 | ### Bug Fixes 502 | 503 | * list css as side effects ([#57](https://github.com/apache-superset/superset-ui-plugins/issues/57)) ([e139bcb](https://github.com/apache-superset/superset-ui-plugins/commit/e139bcb3f1320e3020a313f840057d6ec74e6fac)) 504 | 505 | 506 | 507 | ## [0.10.10](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.9...v0.10.10) (2019-04-10) 508 | 509 | 510 | ### Bug Fixes 511 | 512 | * use correct number format ([#47](https://github.com/apache-superset/superset-ui-plugins/issues/47)) ([b0ae30b](https://github.com/apache-superset/superset-ui-plugins/commit/b0ae30b0869b35946448838d5cacc0c01d3a17f2)) 513 | 514 | 515 | ### Features 516 | 517 | * increment the version number ([#44](https://github.com/apache-superset/superset-ui-plugins/issues/44)) ([355fc7d](https://github.com/apache-superset/superset-ui-plugins/commit/355fc7d45b3f6bd3f22810cdf429522fc6b4a289)) 518 | 519 | 520 | 521 | ## [0.10.9](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.8...v0.10.9) (2019-04-08) 522 | 523 | 524 | ### Bug Fixes 525 | 526 | * y-axis bounds for stacked viz types ([#45](https://github.com/apache-superset/superset-ui-plugins/issues/45)) ([0f8b504](https://github.com/apache-superset/superset-ui-plugins/commit/0f8b504b1338ea20db6bf3253a19068dd8a6808a)) 527 | 528 | 529 | 530 | ## [0.10.8](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.7...v0.10.8) (2019-04-08) 531 | 532 | 533 | ### Bug Fixes 534 | 535 | * remove sticky tooltip when query returns no data in explore view ([#42](https://github.com/apache-superset/superset-ui-plugins/issues/42)) ([789596f](https://github.com/apache-superset/superset-ui-plugins/commit/789596f8c5b9a91da2e9bab7d397a55dc934b8fa)) 536 | 537 | 538 | 539 | ## [0.10.7](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.6...v0.10.7) (2019-04-05) 540 | 541 | 542 | ### Bug Fixes 543 | 544 | * **legacy-preset-chart-nvd3:** stacked bar charts labels ([#40](https://github.com/apache-superset/superset-ui-plugins/issues/40)) ([ec67d3d](https://github.com/apache-superset/superset-ui-plugins/commit/ec67d3d871c27def58393b9c5743d643f9224c90)) 545 | 546 | 547 | 548 | ## [0.10.6](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.5...v0.10.6) (2019-04-04) 549 | 550 | 551 | 552 | ## [0.10.5](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.4...v0.10.5) (2019-04-02) 553 | 554 | 555 | ### Features 556 | 557 | * update dependencies to make plugins compatible with 0.11 ([#38](https://github.com/apache-superset/superset-ui-plugins/issues/38)) ([9cd76ab](https://github.com/apache-superset/superset-ui-plugins/commit/9cd76ab37e872767c31f52b0c21f04469783af1c)) 558 | 559 | 560 | 561 | ## [0.10.4](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.3...v0.10.4) (2019-04-01) 562 | 563 | 564 | ### Bug Fixes 565 | 566 | * big number with trendline fix ([#34](https://github.com/apache-superset/superset-ui-plugins/issues/34)) ([679a3f2](https://github.com/apache-superset/superset-ui-plugins/commit/679a3f2943faeab96c2159cffa7c6462db1a15b8)) 567 | * broken build due to file rename in vega-lite ([#37](https://github.com/apache-superset/superset-ui-plugins/issues/37)) ([17cb5f6](https://github.com/apache-superset/superset-ui-plugins/commit/17cb5f6dc3995881ac9ba471f9b2d5c894743287)) 568 | * exception thrown for charts without a x-axis ([#36](https://github.com/apache-superset/superset-ui-plugins/issues/36)) ([04cae86](https://github.com/apache-superset/superset-ui-plugins/commit/04cae86dcb2599de62c1aa058a67bc7a449f89d5)) 569 | * fine tune time pivot chart tooltip ([#33](https://github.com/apache-superset/superset-ui-plugins/issues/33)) ([6924b98](https://github.com/apache-superset/superset-ui-plugins/commit/6924b9893efd8c4a422a2c5dea99a5562e90e57b)) 570 | * line chart tooltip should use full datetime format ([#24](https://github.com/apache-superset/superset-ui-plugins/issues/24)) ([836818b](https://github.com/apache-superset/superset-ui-plugins/commit/836818b307c50c9245dd6ed627f373bffd6cba51)) 571 | 572 | 573 | ### Features 574 | 575 | * improve the tooltip for the time pivot chart ([#30](https://github.com/apache-superset/superset-ui-plugins/issues/30)) ([ad6ab28](https://github.com/apache-superset/superset-ui-plugins/commit/ad6ab286da05756c066f124c8aa5ebbb6769e5b2)) 576 | * line chart with revised encodeable utilities ([#26](https://github.com/apache-superset/superset-ui-plugins/issues/26)) ([c9b8195](https://github.com/apache-superset/superset-ui-plugins/commit/c9b8195ab71cb42c42a83f8cdcfe1856c5e6e495)) 577 | * update tooltip and use selector ([#31](https://github.com/apache-superset/superset-ui-plugins/issues/31)) ([6a59b21](https://github.com/apache-superset/superset-ui-plugins/commit/6a59b21f1d35aefd62197026ee95782d760ae75b)) 578 | 579 | 580 | 581 | ## [0.10.3](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.2...v0.10.3) (2019-03-22) 582 | 583 | 584 | ### Bug Fixes 585 | 586 | * make pivot table handle null string ([#23](https://github.com/apache-superset/superset-ui-plugins/issues/23)) ([6794209](https://github.com/apache-superset/superset-ui-plugins/commit/67942097f122513c87040dd041acfda3a4331bc9)) 587 | 588 | 589 | ### Features 590 | 591 | * add encodeable utilities for chart ([#15](https://github.com/apache-superset/superset-ui-plugins/issues/15)) ([287d37e](https://github.com/apache-superset/superset-ui-plugins/commit/287d37edefe0044d5aa9456adeaf9813c521793e)) 592 | 593 | 594 | 595 | ## [0.10.2](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.1...v0.10.2) (2019-03-18) 596 | 597 | 598 | 599 | ## [0.10.1](https://github.com/apache-superset/superset-ui-plugins/compare/v0.10.0...v0.10.1) (2019-03-18) 600 | 601 | 602 | ### Bug Fixes 603 | 604 | * bar label for many bars and long labels ([#21](https://github.com/apache-superset/superset-ui-plugins/issues/21)) ([8b9c10a](https://github.com/apache-superset/superset-ui-plugins/commit/8b9c10a58649714fddf83202423dea1bcb38f43d)) 605 | * dual line chart color consistency for secondary y axis ([#18](https://github.com/apache-superset/superset-ui-plugins/issues/18)) ([1ef0d68](https://github.com/apache-superset/superset-ui-plugins/commit/1ef0d68dfdcfe4eff4498cec9d8454b821cc49bc)) 606 | * nvd3 line chart y axis bounds ([#17](https://github.com/apache-superset/superset-ui-plugins/issues/17)) ([1c0e682](https://github.com/apache-superset/superset-ui-plugins/commit/1c0e682af1e442cfb827a6acc8a7892e895758a6)) 607 | * show only necessary tick labels on log scale ([#19](https://github.com/apache-superset/superset-ui-plugins/issues/19)) ([2f35d0c](https://github.com/apache-superset/superset-ui-plugins/commit/2f35d0ca9b1614b4131878379e34337add724023)) 608 | 609 | 610 | ### Features 611 | 612 | * add properties for font sizing ([#10](https://github.com/apache-superset/superset-ui-plugins/issues/10)) ([d07f60c](https://github.com/apache-superset/superset-ui-plugins/commit/d07f60c0d0d894f0dfd069aa8c732a6be8e898d8)) 613 | 614 | 615 | 616 | # [0.10.0](https://github.com/apache-superset/superset-ui-plugins/compare/v0.1.1...v0.10.0) (2019-03-05) 617 | 618 | 619 | ### Bug Fixes 620 | 621 | * **legacy-preset-chart-nvd3:** redraw bar values after legend change ([#7](https://github.com/apache-superset/superset-ui-plugins/issues/7)) ([28b1f75](https://github.com/apache-superset/superset-ui-plugins/commit/28b1f75461a169af41cb8100d6e9f38ac4dbc54d)) 622 | * **legacy-preset-chart-nvd3:** redraw markers after legend interaction ([#6](https://github.com/apache-superset/superset-ui-plugins/issues/6)) ([b257c32](https://github.com/apache-superset/superset-ui-plugins/commit/b257c32f1a63451495d419195afabe844f27a17c)) 623 | * **legacy-preset-chart-nvd3:** tooltip's disappearance and stickiness ([#1](https://github.com/apache-superset/superset-ui-plugins/issues/1)) ([0cc1ea8](https://github.com/apache-superset/superset-ui-plugins/commit/0cc1ea8e1211b2d5d4af9a70313bc26e6ea5b387)) 624 | * 🐛 broken unit test due to missing babel-polyfill ([346ca5c](https://github.com/apache-superset/superset-ui-plugins/commit/346ca5c07e06a622565dbf90486fef2ab0ea6baf)) 625 | * resolve issues post `0.10.0` ([7b0fd6d](https://github.com/apache-superset/superset-ui-plugins/commit/7b0fd6d902dfb186798228e543d95d9fde79c089)) 626 | 627 | 628 | ### Features 629 | 630 | * **legacy-preset-chart-nvd3:** show negative values on bars ([#8](https://github.com/apache-superset/superset-ui-plugins/issues/8)) ([8a2dbdc](https://github.com/apache-superset/superset-ui-plugins/commit/8a2dbdc48f8556c0271d930b3833d1d6e39531d2)) 631 | * 🎸 line chart makes first appearance ([e1c9ac2](https://github.com/apache-superset/superset-ui-plugins/commit/e1c9ac2b217351b5acbc67267915e98121338c37)) 632 | * add country map of bulgaria in superset-ui-legacy-plugin-chart-country-map ([#2](https://github.com/apache-superset/superset-ui-plugins/issues/2)) ([b5fd6e4](https://github.com/apache-superset/superset-ui-plugins/commit/b5fd6e49850bdca6fd5ec5780079ec5493aa0130)) 633 | * bump data-ui/xy-chart version ([5bb28f3](https://github.com/apache-superset/superset-ui-plugins/commit/5bb28f33791b132ff96ffeb849397e7e9d73db43)) 634 | 635 | 636 | 637 | ## [0.1.1](https://github.com/apache-superset/superset-ui-plugins/compare/v0.1.0...v0.1.1) (2019-02-14) 638 | 639 | 640 | 641 | # [0.1.0](https://github.com/apache-superset/superset-ui-plugins/compare/v0.0.3...v0.1.0) (2019-02-13) 642 | 643 | 644 | 645 | ## [0.0.3](https://github.com/apache-superset/superset-ui-plugins/compare/v0.0.2...v0.0.3) (2019-02-13) 646 | 647 | 648 | 649 | ## [0.0.2](https://github.com/apache-superset/superset-ui-plugins/compare/v0.0.1...v0.0.2) (2019-02-12) 650 | 651 | 652 | 653 | ## [0.0.1](https://github.com/apache-superset/superset-ui-plugins/compare/v0.0.1-alpha.0...v0.0.1) (2019-02-09) 654 | 655 | 656 | 657 | ## 0.0.1-alpha.0 (2019-02-07) 658 | 659 | 660 | 661 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # @superset-ui/plugins 🔌💡 2 | 3 | ### UPDATE: The code in this repository has been migrated and merged into [@superset-ui](https://github.com/apache-superset/superset-ui). 4 | 5 | [![Codecov branch](https://img.shields.io/codecov/c/github/apache-superset/superset-ui-plugins/master.svg?style=flat-square)](https://codecov.io/gh/apache-superset/superset-ui-plugins/branch/master) 6 | [![Build Status](https://img.shields.io/travis/com/apache-superset/superset-ui-plugins/master.svg?style=flat-square)](https://travis-ci.com/apache-superset/superset-ui-plugins) 7 | [![David](https://img.shields.io/david/dev/apache-superset/superset-ui-plugins.svg?style=flat-square)](https://david-dm.org/apache-superset/superset-ui-plugins?type=dev) 8 | [![Netlify Status](https://api.netlify.com/api/v1/badges/cef8fedc-2938-4f20-9823-fcd3cd2f30b3/deploy-status)](https://app.netlify.com/sites/superset-ui-plugins/deploys) 9 | 10 | `@superset-ui/legacy-*` packages are extracted from the classic 11 | [Apache Superset](https://github.com/apache/incubator-superset) and converted into plugins. These 12 | packages are extracted with minimal changes (almost as-is). They also depend on legacy API 13 | (`viz.py`) to function. 14 | 15 | `@superset-ui/plugin-*` packages are newer and higher quality in general. A key difference that they 16 | do not depend on `viz.py` (which contain visualization-specific python code) and interface with 17 | `/api/v1/query/` instead: a new generic endpoint instead meant to serve all visualizations. Also 18 | should be written in Typescript. 19 | 20 | We are not accepting pull requests for new community-contributed plugins to be merged into this 21 | repository at the moment. We will keep it lean for now to improve the standard and reduce 22 | operational load on maintenance. Bug fixes are welcome. 23 | 24 | To setup your own plugin repository, we current have a template for new repository that you can copy 25 | from. Go to 26 | ["superset-ui-plugins-template"](https://github.com/apache-superset/superset-ui-plugins-template) 27 | and look for the green "Use this template" button. 28 | 29 | ## Demo (Storybook) 30 | 31 | Most recent release: https://apache-superset.github.io/superset-ui-plugins/ 32 | 33 | Current master: https://superset-ui-plugins.netlify.com 34 | 35 | ## Packages 36 | 37 | | Package | Version | Note | 38 | | ------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ | 39 | | [@superset-ui/plugin-chart-table](https://github.com/apache-superset/superset-ui-plugins/tree/master/packages/superset-ui-plugin-chart-table) | [![Version](https://img.shields.io/npm/v/@superset-ui/plugin-chart-table.svg?style=flat-square)](https://img.shields.io/npm/v/@superset-ui/plugin-chart-table.svg?style=flat-square) | | 40 | 41 | | Package | Version | 42 | | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 43 | | [@superset-ui/legacy-plugin-chart-event-flow](https://github.com/apache-superset/superset-ui-plugins/tree/master/packages/superset-ui-legacy-plugin-chart-event-flow) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-event-flow.svg?style=flat-square)](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-event-flow.svg?style=flat-square) | 44 | | [@superset-ui/legacy-plugin-chart-word-cloud](https://github.com/apache-superset/superset-ui-plugins/tree/master/packages/superset-ui-legacy-plugin-chart-word-cloud) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-word-cloud.svg?style=flat-square)](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-word-cloud.svg?style=flat-square) | 45 | 46 | 47 | ## Contribution and development guide 48 | 49 | Please read the 50 | [contributing guidelines](https://github.com/apache-superset/superset-ui/blob/master/CONTRIBUTING.md) 51 | which include development environment setup and other things you should know about coding in this 52 | repo. 53 | 54 | To build only selected plugins, 55 | 56 | ```bash 57 | node scripts/build.js "*legacy-plugin-chart-table" 58 | ``` 59 | 60 | ### License 61 | 62 | Apache-2.0 63 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line no-undef, import/no-extraneous-dependencies 2 | const { getConfig } = require('@airbnb/config-babel'); 3 | 4 | const config = getConfig({ 5 | library: true, 6 | react: true, 7 | next: true, 8 | node: process.env.NODE_ENV === 'test', 9 | typescript: true, 10 | env: { 11 | targets: false, 12 | }, 13 | }); 14 | 15 | if (process.env.NODE_ENV !== 'test') { 16 | config.presets[0][1].modules = false; 17 | } 18 | 19 | // Override to allow transpile es modules inside vega-lite 20 | config.ignore = config.ignore.filter(item => item !== 'node_modules/'); 21 | config.ignore.push('node_modules/(?!(vega-lite|lodash-es))'); 22 | 23 | // eslint-disable-next-line no-undef 24 | module.exports = config; 25 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = require('@superset-ui/commit-config/commitlint.config'); 2 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "lerna": "3.2.1", 3 | "npmClient": "yarn", 4 | "packages": [ 5 | "packages/*" 6 | ], 7 | "useWorkspaces": true, 8 | "version": "0.11.21" 9 | } 10 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@superset-ui/plugins-monorepo", 3 | "version": "0.0.0-master", 4 | "description": "Superset UI Plugins", 5 | "private": true, 6 | "scripts": { 7 | "build": "yarn babel && yarn type && yarn build:assets", 8 | "babel": "yarn babel:cjs && yarn babel:esm", 9 | "babel:cjs": "nimbus babel --clean --workspaces=\"@superset-ui/!(plugins-demo)\" --config-file=../../babel.config.js", 10 | "babel:esm": "nimbus babel --clean --workspaces=\"@superset-ui/!(plugins-demo)\" --esm --config-file=../../babel.config.js", 11 | "build:assets": "node ./scripts/buildAssets.js", 12 | "clean": "rm -rf ./packages/**/{lib,esm}", 13 | "commit": "superset-commit", 14 | "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0", 15 | "format": "yarn prettier --write", 16 | "jest": "NODE_ENV=test nimbus jest --coverage --verbose", 17 | "lint": "nimbus eslint && nimbus prettier --check", 18 | "lint:fix": "nimbus eslint --fix", 19 | "prettier": "nimbus prettier", 20 | "test": "yarn type && yarn jest", 21 | "test:watch": "yarn lint:fix && yarn jest --watch", 22 | "type": "nimbus typescript --build --reference-workspaces", 23 | "prepare-release": "git checkout master && git pull --rebase origin master && lerna bootstrap && yarn install && yarn test", 24 | "prerelease": "yarn build", 25 | "pretest": "yarn lint", 26 | "release": "yarn prepare-release && lerna publish --exact && yarn postrelease", 27 | "postrelease": "lerna run deploy-demo", 28 | "storybook": "cd packages/superset-ui-plugins-demo && yarn storybook" 29 | }, 30 | "repository": "https://github.com/apache-superset/superset-ui-plugins.git", 31 | "keywords": [ 32 | "apache", 33 | "superset", 34 | "data", 35 | "analytics", 36 | "analysis", 37 | "visualization", 38 | "react", 39 | "d3", 40 | "data-ui", 41 | "vx" 42 | ], 43 | "license": "Apache-2.0", 44 | "devDependencies": { 45 | "@airbnb/config-babel": "^2.2.2", 46 | "@airbnb/config-eslint": "^2.5.1", 47 | "@airbnb/config-jest": "^2.2.2", 48 | "@airbnb/config-prettier": "^2.1.1", 49 | "@airbnb/config-typescript": "^2.2.2", 50 | "@airbnb/nimbus": "^2.2.3", 51 | "@superset-ui/commit-config": "^0.0.9", 52 | "@superset-ui/superset-ui": "^0.12.15", 53 | "@types/enzyme": "^3.10.3", 54 | "@types/jest": "^25.1.3", 55 | "@types/jsdom": "^12.2.4", 56 | "@types/react": "^16.9.23", 57 | "@types/react-test-renderer": "^16.9.2", 58 | "csstype": "^2.6.3", 59 | "enzyme": "^3.10.0", 60 | "enzyme-adapter-react-16": "^1.15.1", 61 | "enzyme-to-json": "^3.4.3", 62 | "fast-glob": "^3.0.1", 63 | "fs-extra": "^8.0.1", 64 | "husky": "^4.2.1", 65 | "identity-obj-proxy": "^3.0.0", 66 | "jest-mock-console": "^1.0.0", 67 | "lerna": "^3.15.0", 68 | "lint-staged": "^10.0.7", 69 | "react": "^16.9.23", 70 | "react-dom": "^16.9.23", 71 | "react-test-renderer": "^16.9.2" 72 | }, 73 | "engines": { 74 | "node": ">=10.10.0", 75 | "npm": ">=6.8.0", 76 | "yarn": ">=1.13.0" 77 | }, 78 | "workspaces": [ 79 | "./packages/*" 80 | ], 81 | "browserslist": [ 82 | "last 3 chrome versions", 83 | "last 3 firefox versions", 84 | "last 3 safari versions", 85 | "last 3 edge versions" 86 | ], 87 | "nimbus": { 88 | "drivers": [ 89 | { "driver": "babel", "strategy": "none" }, 90 | "eslint", 91 | "jest", 92 | "prettier", 93 | "typescript" 94 | ], 95 | "settings": { 96 | "library": true, 97 | "react": true, 98 | "next": true, 99 | "env": { 100 | "targets": false 101 | } 102 | }, 103 | "jest": { 104 | "timers": "real", 105 | "setupFilesAfterEnv": [ 106 | "@airbnb/config-jest/enzyme", 107 | "./scripts/setupJest.js" 108 | ], 109 | "transformIgnorePatterns": [ 110 | "node_modules/(?!(vega-lite|lodash-es))" 111 | ], 112 | "coverageThreshold": { 113 | "global": { 114 | "branches": 1, 115 | "functions": 1, 116 | "lines": 1, 117 | "statements": 1 118 | } 119 | }, 120 | "moduleNameMapper": { 121 | "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "/__mocks__/fileMock.js", 122 | "\\.(css|less)$": "identity-obj-proxy" 123 | } 124 | }, 125 | "eslint": { 126 | "overrides": [ 127 | { 128 | "files": "*.test.{js,jsx,ts,tsx}", 129 | "rules": { 130 | "import/no-extraneous-dependencies": "off", 131 | "promise/param-names": "off", 132 | "import/extensions": "off", 133 | "jest/require-to-throw-message": "off", 134 | "jest/no-test-return-statement": "off", 135 | "jest/no-expect-resolves": "off", 136 | "jest/no-test-callback": "off" 137 | } 138 | }, 139 | { 140 | "files": "*.{js,jsx,ts,tsx}", 141 | "rules": { 142 | "react/jsx-no-literals": "off", 143 | "prefer-exponentiation-operator": "off", 144 | "@typescript-eslint/no-explicit-any": [ 145 | "warn", 146 | { 147 | "fixToUnknown": false 148 | } 149 | ] 150 | } 151 | } 152 | ] 153 | }, 154 | "typescript": { 155 | "compilerOptions": { 156 | "emitDeclarationOnly": true 157 | } 158 | } 159 | }, 160 | "husky": { 161 | "hooks": { 162 | "pre-commit": "lint-staged", 163 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS" 164 | } 165 | }, 166 | "lint-staged": { 167 | "./packages/*/{src,test,storybook}/**/*.{js,jsx,ts,tsx,json,md}": [ 168 | "yarn prettier --write", 169 | "git add" 170 | ] 171 | }, 172 | "resolutions": { 173 | "**/@types/react": "^16.9.23" 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /packages/superset-ui-legacy-plugin-chart-event-flow/README.md: -------------------------------------------------------------------------------- 1 | ## @superset-ui/legacy-plugin-chart-event-flow 2 | 3 | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-event-flow.svg?style=flat-square)](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-event-flow.svg?style=flat-square) 4 | [![David (path)](https://img.shields.io/david/apache-superset/superset-ui-plugins.svg?path=packages%2Fsuperset-ui-legacy-plugin-chart-event-flow&style=flat-square)](https://david-dm.org/apache-superset/superset-ui-plugins?path=packages/superset-ui-legacy-plugin-chart-event-flow) 5 | 6 | This plugin provides Event Flow for Superset. 7 | 8 | ### Usage 9 | 10 | Configure `key`, which can be any `string`, and register the plugin. This `key` will be used to lookup this chart throughout the app. 11 | 12 | ```js 13 | import EventFlowChartPlugin from '@superset-ui/legacy-plugin-chart-event-flow'; 14 | 15 | new EventFlowChartPlugin() 16 | .configure({ key: 'event-flow' }) 17 | .register(); 18 | ``` 19 | 20 | Then use it via `SuperChart`. See [storybook](https://apache-superset.github.io/superset-ui-plugins/?selectedKind=plugin-chart-event-flow) for more details. 21 | 22 | ```js 23 | 32 | ``` -------------------------------------------------------------------------------- /packages/superset-ui-legacy-plugin-chart-event-flow/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@superset-ui/legacy-plugin-chart-event-flow", 3 | "version": "0.11.15", 4 | "description": "Superset Legacy Chart - Event Flow", 5 | "sideEffects": [ 6 | "*.css" 7 | ], 8 | "main": "lib/index.js", 9 | "module": "esm/index.js", 10 | "files": [ 11 | "esm", 12 | "lib" 13 | ], 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/apache-superset/superset-ui-plugins.git" 17 | }, 18 | "keywords": [ 19 | "superset" 20 | ], 21 | "author": "Superset", 22 | "license": "Apache-2.0", 23 | "bugs": { 24 | "url": "https://github.com/apache-superset/superset-ui-plugins/issues" 25 | }, 26 | "homepage": "https://github.com/apache-superset/superset-ui-plugins#readme", 27 | "publishConfig": { 28 | "access": "public" 29 | }, 30 | "dependencies": { 31 | "@data-ui/event-flow": "^0.0.84", 32 | "prop-types": "^15.6.2" 33 | }, 34 | "peerDependencies": { 35 | "@superset-ui/chart": "^0.12.0", 36 | "@superset-ui/translation": "^0.12.0", 37 | "react": "^15 || ^16" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /packages/superset-ui-legacy-plugin-chart-event-flow/src/EventFlow.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | /* eslint-disable react/forbid-prop-types */ 20 | import React from 'react'; 21 | import PropTypes from 'prop-types'; 22 | import { App } from '@data-ui/event-flow'; 23 | import { t } from '@superset-ui/translation'; 24 | 25 | const propTypes = { 26 | data: PropTypes.array, 27 | height: PropTypes.number, 28 | /* eslint-disable-next-line */ 29 | initialMinEventCount: PropTypes.number, 30 | width: PropTypes.number, 31 | }; 32 | const defaultProps = { 33 | data: null, 34 | height: 400, 35 | width: 400, 36 | }; 37 | 38 | function CustomEventFlow(props) { 39 | const { data, height, initialMinEventCount, width } = props; 40 | if (data) { 41 | return ( 42 | 49 | ); 50 | } 51 | 52 | return ( 53 |
54 |
{t('Sorry, there appears to be no data')}
55 |
56 | ); 57 | } 58 | 59 | CustomEventFlow.propTypes = propTypes; 60 | CustomEventFlow.defaultProps = defaultProps; 61 | 62 | export default CustomEventFlow; 63 | -------------------------------------------------------------------------------- /packages/superset-ui-legacy-plugin-chart-event-flow/src/images/thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache-superset/superset-ui-plugins/75fd10c9c82cec17608be820b03f924be0b5786e/packages/superset-ui-legacy-plugin-chart-event-flow/src/images/thumbnail.png -------------------------------------------------------------------------------- /packages/superset-ui-legacy-plugin-chart-event-flow/src/images/thumbnailLarge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache-superset/superset-ui-plugins/75fd10c9c82cec17608be820b03f924be0b5786e/packages/superset-ui-legacy-plugin-chart-event-flow/src/images/thumbnailLarge.png -------------------------------------------------------------------------------- /packages/superset-ui-legacy-plugin-chart-event-flow/src/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { t } from '@superset-ui/translation'; 20 | import { ChartMetadata, ChartPlugin } from '@superset-ui/chart'; 21 | import thumbnail from './images/thumbnail.png'; 22 | 23 | const metadata = new ChartMetadata({ 24 | credits: ['https://github.com/williaster/data-ui'], 25 | description: '', 26 | name: t('Event Flow'), 27 | thumbnail, 28 | useLegacyApi: true, 29 | }); 30 | 31 | export default class EventFlowChartPlugin extends ChartPlugin { 32 | constructor() { 33 | super({ 34 | loadChart: () => import('./EventFlow'), 35 | loadTransformProps: () => import('./transformProps.js'), 36 | metadata, 37 | }); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /packages/superset-ui-legacy-plugin-chart-event-flow/src/transformProps.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { cleanEvents, TS, EVENT_NAME, ENTITY_ID } from '@data-ui/event-flow'; 20 | 21 | export default function transformProps(chartProps) { 22 | const { formData, queryData, width, height } = chartProps; 23 | const { allColumnsX, entity, minLeafNodeEventCount } = formData; 24 | const { data } = queryData; 25 | 26 | const hasData = data && data.length > 0; 27 | if (hasData) { 28 | const userKey = entity; 29 | const eventNameKey = allColumnsX; 30 | 31 | // map from the Superset form fields to 's expected data keys 32 | const accessorFunctions = { 33 | [ENTITY_ID]: datum => String(datum[userKey]), 34 | [EVENT_NAME]: datum => datum[eventNameKey], 35 | // eslint-disable-next-line no-underscore-dangle 36 | [TS]: datum => new Date(datum.__timestamp), 37 | }; 38 | 39 | const cleanData = cleanEvents(data, accessorFunctions); 40 | 41 | return { 42 | data: cleanData, 43 | height, 44 | initialMinEventCount: minLeafNodeEventCount, 45 | width, 46 | }; 47 | } 48 | 49 | return { data: null, height, width }; 50 | } 51 | -------------------------------------------------------------------------------- /packages/superset-ui-legacy-plugin-chart-word-cloud/README.md: -------------------------------------------------------------------------------- 1 | ## @superset-ui/legacy-plugin-chart-word-cloud 2 | 3 | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-word-cloud.svg?style=flat-square)](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-word-cloud.svg?style=flat-square) 4 | [![David (path)](https://img.shields.io/david/apache-superset/superset-ui-plugins.svg?path=packages%2Fsuperset-ui-legacy-plugin-chart-word-cloud&style=flat-square)](https://david-dm.org/apache-superset/superset-ui-plugins?path=packages/superset-ui-legacy-plugin-chart-word-cloud) 5 | 6 | This plugin provides Word Cloud for Superset. 7 | 8 | ### Usage 9 | 10 | Configure `key`, which can be any `string`, and register the plugin. This `key` will be used to lookup this chart throughout the app. 11 | 12 | ```js 13 | import WordCloudChartPlugin from '@superset-ui/legacy-plugin-chart-word-cloud'; 14 | 15 | new WordCloudChartPlugin() 16 | .configure({ key: 'word-cloud' }) 17 | .register(); 18 | ``` 19 | 20 | Then use it via `SuperChart`. See [storybook](https://apache-superset.github.io/superset-ui-plugins/?selectedKind=plugin-chart-word-cloud) for more details. 21 | 22 | ```js 23 | 32 | ``` -------------------------------------------------------------------------------- /packages/superset-ui-legacy-plugin-chart-word-cloud/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@superset-ui/legacy-plugin-chart-word-cloud", 3 | "version": "0.11.15", 4 | "description": "Superset Legacy Chart - Word Cloud", 5 | "sideEffects": [ 6 | "*.css" 7 | ], 8 | "main": "lib/index.js", 9 | "module": "esm/index.js", 10 | "files": [ 11 | "esm", 12 | "lib" 13 | ], 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/apache-superset/superset-ui-plugins.git" 17 | }, 18 | "keywords": [ 19 | "superset" 20 | ], 21 | "author": "Superset", 22 | "license": "Apache-2.0", 23 | "bugs": { 24 | "url": "https://github.com/apache-superset/superset-ui-plugins/issues" 25 | }, 26 | "homepage": "https://github.com/apache-superset/superset-ui-plugins#readme", 27 | "publishConfig": { 28 | "access": "public" 29 | }, 30 | "dependencies": { 31 | "d3": "^3.5.17", 32 | "d3-cloud": "^1.2.1", 33 | "prop-types": "^15.6.2" 34 | }, 35 | "peerDependencies": { 36 | "@superset-ui/chart": "^0.12.0", 37 | "@superset-ui/color": "^0.12.0", 38 | "@superset-ui/translation": "^0.12.0" 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /packages/superset-ui-legacy-plugin-chart-word-cloud/src/ReactWordCloud.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { reactify } from '@superset-ui/chart'; 20 | import Component from './WordCloud'; 21 | 22 | export default reactify(Component); 23 | -------------------------------------------------------------------------------- /packages/superset-ui-legacy-plugin-chart-word-cloud/src/WordCloud.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | /* eslint-disable react/sort-prop-types */ 20 | 21 | import d3 from 'd3'; 22 | import PropTypes from 'prop-types'; 23 | import cloudLayout from 'd3-cloud'; 24 | import { CategoricalColorNamespace } from '@superset-ui/color'; 25 | 26 | const ROTATION = { 27 | square: () => Math.floor(Math.random() * 2) * 90, 28 | flat: () => 0, 29 | random: () => Math.floor(Math.random() * 6 - 3) * 30, 30 | }; 31 | 32 | const propTypes = { 33 | data: PropTypes.arrayOf( 34 | PropTypes.shape({ 35 | size: PropTypes.number, 36 | text: PropTypes.string, 37 | }), 38 | ), 39 | width: PropTypes.number, 40 | height: PropTypes.number, 41 | rotation: PropTypes.string, 42 | sizeRange: PropTypes.arrayOf(PropTypes.number), 43 | colorScheme: PropTypes.string, 44 | }; 45 | 46 | function WordCloud(element, props) { 47 | const { data, width, height, rotation, sizeRange, colorScheme } = props; 48 | 49 | const chart = d3.select(element); 50 | chart.classed('superset-legacy-chart-word-cloud', true); 51 | const size = [width, height]; 52 | const rotationFn = ROTATION[rotation] || ROTATION.flat; 53 | 54 | const scale = d3.scale 55 | .linear() 56 | .range(sizeRange) 57 | .domain(d3.extent(data, d => d.size)); 58 | 59 | const layout = cloudLayout() 60 | .size(size) 61 | .words(data) 62 | .padding(5) 63 | .rotate(rotationFn) 64 | .font('Helvetica') 65 | .fontWeight('bold') 66 | .fontSize(d => scale(d.size)); 67 | 68 | const colorFn = CategoricalColorNamespace.getScale(colorScheme); 69 | 70 | function draw(words) { 71 | chart.selectAll('*').remove(); 72 | 73 | const [w, h] = layout.size(); 74 | 75 | chart 76 | .append('svg') 77 | .attr('width', w) 78 | .attr('height', h) 79 | .append('g') 80 | .attr('transform', `translate(${w / 2},${h / 2})`) 81 | .selectAll('text') 82 | .data(words) 83 | .enter() 84 | .append('text') 85 | .style('font-size', d => `${d.size}px`) 86 | .style('font-weight', 'bold') 87 | .style('font-family', 'Helvetica') 88 | .style('fill', d => colorFn(d.text)) 89 | .attr('text-anchor', 'middle') 90 | .attr('transform', d => `translate(${d.x}, ${d.y}) rotate(${d.rotate})`) 91 | .text(d => d.text); 92 | } 93 | 94 | layout.on('end', draw).start(); 95 | } 96 | 97 | WordCloud.displayName = 'WordCloud'; 98 | WordCloud.propTypes = propTypes; 99 | 100 | export default WordCloud; 101 | -------------------------------------------------------------------------------- /packages/superset-ui-legacy-plugin-chart-word-cloud/src/images/thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache-superset/superset-ui-plugins/75fd10c9c82cec17608be820b03f924be0b5786e/packages/superset-ui-legacy-plugin-chart-word-cloud/src/images/thumbnail.png -------------------------------------------------------------------------------- /packages/superset-ui-legacy-plugin-chart-word-cloud/src/images/thumbnailLarge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache-superset/superset-ui-plugins/75fd10c9c82cec17608be820b03f924be0b5786e/packages/superset-ui-legacy-plugin-chart-word-cloud/src/images/thumbnailLarge.png -------------------------------------------------------------------------------- /packages/superset-ui-legacy-plugin-chart-word-cloud/src/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { t } from '@superset-ui/translation'; 20 | import { ChartMetadata, ChartPlugin } from '@superset-ui/chart'; 21 | import transformProps from './transformProps'; 22 | import thumbnail from './images/thumbnail.png'; 23 | 24 | const metadata = new ChartMetadata({ 25 | credits: ['https://github.com/jasondavies/d3-cloud'], 26 | description: '', 27 | name: t('Word Cloud'), 28 | thumbnail, 29 | useLegacyApi: true, 30 | }); 31 | 32 | export default class WordCloudChartPlugin extends ChartPlugin { 33 | constructor() { 34 | super({ 35 | loadChart: () => import('./ReactWordCloud.js'), 36 | metadata, 37 | transformProps, 38 | }); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /packages/superset-ui-legacy-plugin-chart-word-cloud/src/transformProps.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | function transformData(data, formData) { 20 | const { metric, series } = formData; 21 | 22 | const transformedData = data.map(datum => ({ 23 | size: datum[metric.label || metric], 24 | text: datum[series], 25 | })); 26 | 27 | return transformedData; 28 | } 29 | 30 | export default function transformProps(chartProps) { 31 | const { width, height, formData, queryData } = chartProps; 32 | const { colorScheme, rotation, sizeTo, sizeFrom } = formData; 33 | 34 | return { 35 | width, 36 | height, 37 | data: transformData(queryData.data, formData), 38 | colorScheme, 39 | rotation, 40 | sizeRange: [sizeFrom, sizeTo], 41 | }; 42 | } 43 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-icicle-event/README.md: -------------------------------------------------------------------------------- 1 | ## @superset-ui/plugin-chart-icicle 2 | 3 | ## WIP 4 | 5 | This is a work in progress with the design being finalized. 6 | 7 | This plugin provides Icicle Event Chart for Superset. 8 | 9 | ### Usage 10 | 11 | Configure `key`, which can be any `string`, and register the plugin. This `key` will be used to lookup this chart throughout the app. 12 | 13 | ```js 14 | import IcicleEventVizPlugin from '@superset-ui/plugin-chart-icicle-event'; 15 | 16 | new IcicleEventVizPlugin() 17 | .configure({ key: 'icicle' }) 18 | .register(); 19 | ``` 20 | 21 | Then use it via `SuperChart`. A link to Storybook for the Icicle Event Chart will be available here in the future for more details. 22 | 23 | ```js 24 | 33 | ``` 34 | 35 | ### Current Prototype (Subject to Change) 36 | 37 | ![Current Prototype](./src/images/thumbnail.png) 38 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-icicle-event/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@superset-ui/plugin-chart-icicle-event", 3 | "version": "0.11.15", 4 | "description": "Superset Chart Plugin - Icicle Event", 5 | "sideEffects": [ 6 | "*.css" 7 | ], 8 | "main": "lib/index.js", 9 | "module": "esm/index.js", 10 | "files": [ 11 | "esm", 12 | "lib", 13 | "types" 14 | ], 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/apache-superset/superset-ui-plugins.git" 18 | }, 19 | "keywords": [ 20 | "superset" 21 | ], 22 | "author": "Superset", 23 | "license": "Apache-2.0", 24 | "bugs": { 25 | "url": "https://github.com/apache-superset/superset-ui-plugins/issues" 26 | }, 27 | "homepage": "https://github.com/apache-superset/superset-ui-plugins#readme", 28 | "publishConfig": { 29 | "access": "public" 30 | }, 31 | "dependencies": { 32 | "@types/d3": "^5.7.2", 33 | "@types/d3-hierarchy": "^1.1.6", 34 | "@types/d3-selection": "^1.4.1", 35 | "@types/memoize-one": "^5.1.2", 36 | "d3-array": "^2.2.0", 37 | "d3-hierarchy": "^1.1.8", 38 | "d3-selection": "^1.4.0", 39 | "lodash": "^4.17.11", 40 | "memoize-one": "^5.0.5", 41 | "prop-types": "^15.6.2" 42 | }, 43 | "peerDependencies": { 44 | "@superset-ui/chart": "^0.12.0", 45 | "@superset-ui/color": "^0.12.0", 46 | "@superset-ui/core": "^0.12.0", 47 | "@superset-ui/translation": "^0.12.0", 48 | "react": "^16.2" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-icicle-event/src/IcicleEventChart.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import React, { Component, createRef } from 'react'; 20 | import { HierarchyRectangularNode } from 'd3-hierarchy'; 21 | import { BaseType, select as d3Select } from 'd3-selection'; 22 | import { IcicleEventNode } from './IcicleEventNode'; 23 | import { x0, y0, rectWidth, rectHeight } from './utils/RenderedIcicleAccessors'; 24 | 25 | interface Props { 26 | className?: string; 27 | width: number; 28 | height: number; 29 | boxMargin: { 30 | x: number; 31 | y: number; 32 | }; 33 | color: (name: string) => string; 34 | contentRenderer: ( 35 | datum: HierarchyRectangularNode, 36 | container: BaseType, 37 | rect: { 38 | width: number; 39 | height: number; 40 | }, 41 | ) => void; 42 | d3TreeRoot: HierarchyRectangularNode; 43 | isVertical: boolean; 44 | rounding: number; 45 | transitionDuration: number; 46 | } 47 | 48 | function defaultContentRenderer( 49 | datum: HierarchyRectangularNode, 50 | container: HTMLDivElement, 51 | rect: { width: number; height: number }, 52 | ) { 53 | const minRectHeight = 20; 54 | const minRectWidth = 10; 55 | 56 | d3Select(container) 57 | .attr('class', 'icicleContent') 58 | .style('text-overflow', 'ellipsis') 59 | .style('white-space', 'nowrap') 60 | .style('overflow', 'hidden') 61 | .style('font-size', `${rect.height / 2}px`) 62 | .style('line-height', `${rect.height}px`) 63 | .text(`${rect.height > minRectHeight && rect.width > minRectWidth ? datum.data.name : ''}`); 64 | } 65 | 66 | export default class IcicleEventChart extends Component { 67 | private chartRef = createRef(); 68 | 69 | static defaultProps = { 70 | boxMargin: { 71 | x: 1, 72 | y: 3, 73 | }, 74 | color: (name: string) => 'pink', 75 | contentRenderer: defaultContentRenderer, 76 | }; 77 | 78 | constructor(props: Props) { 79 | super(props); 80 | 81 | this.renderIcicleChart = this.renderIcicleChart.bind(this); 82 | } 83 | 84 | componentDidMount() { 85 | this.renderIcicleChart(); 86 | } 87 | 88 | // Check for changed data to rerender the icicle chart 89 | componentDidUpdate(prevProps: Props) { 90 | const root = this.props.d3TreeRoot; 91 | const prevRoot = prevProps.d3TreeRoot; 92 | 93 | if (root.data.id !== prevRoot.data.id || root.data.value !== prevRoot.data.value) { 94 | this.renderIcicleChart(); 95 | } 96 | } 97 | 98 | // Creates chart using svg & chartRef to the div element 99 | renderIcicleChart() { 100 | const { boxMargin, color, contentRenderer, isVertical, width, height, rounding } = this.props; 101 | 102 | const root = this.props.d3TreeRoot; 103 | 104 | // Clear all elements and redraw the Icicle Chart 105 | d3Select(this.chartRef.current) 106 | .selectAll('*') 107 | .remove(); 108 | 109 | const svg = d3Select(this.chartRef.current) 110 | .append('svg') 111 | .style('width', `${width}px`) 112 | .style('height', `${height}px`) 113 | .style('overflow', 'hidden'); 114 | 115 | const cell = svg 116 | .selectAll('g') 117 | .data(root.descendants()) 118 | .enter() 119 | .append('g') 120 | .attr( 121 | 'transform', 122 | d => `translate(${y0(isVertical, d) + boxMargin.x},${x0(isVertical, d) + boxMargin.y})`, 123 | ) 124 | .attr('key', (d, i) => `${i}`); 125 | 126 | // Create the color coded rectangles for the events 127 | cell 128 | .append('rect') 129 | .attr('width', d => rectWidth(isVertical, boxMargin, d)) 130 | .attr('height', d => rectHeight(isVertical, boxMargin, d)) 131 | .attr('rx', rounding) 132 | .attr('fill', d => color(d.data.name ?? '')) 133 | .style('cursor', 'pointer'); 134 | 135 | // Create container for each rectangle to append content (name of event) 136 | const content = cell 137 | .append('foreignObject') 138 | .classed('container', true) 139 | .attr('pointer-events', 'none') 140 | .style('width', d => `${rectWidth(isVertical, boxMargin, d)}px`) 141 | .style('height', d => `${rectHeight(isVertical, boxMargin, d)}px`) 142 | .style('padding', '0px') 143 | .style('overflow', 'hidden') 144 | .style('background', 'none'); 145 | 146 | if (!isVertical) { 147 | content 148 | .attr('transform', d => `translate(${rectWidth(isVertical, boxMargin, d)}) rotate(90)`) 149 | .style('height', d => `${rectWidth(isVertical, boxMargin, d)}px`) 150 | .style('width', d => `${rectHeight(isVertical, boxMargin, d)}px`); 151 | } 152 | 153 | content 154 | .append('xhtml:div') 155 | .style('width', '100%') 156 | .style('height', '100%') 157 | .style('padding-left', '2px') 158 | .each((d, i, elements) => 159 | contentRenderer(d, elements[i], { 160 | height: rectHeight(isVertical, boxMargin, d), 161 | width: rectWidth(isVertical, boxMargin, d), 162 | }), 163 | ); 164 | } 165 | 166 | render() { 167 | return ( 168 |
169 |
170 |
171 | ); 172 | } 173 | } 174 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-icicle-event/src/IcicleEventNode.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | export type IcicleEventNode = { 20 | id: string; 21 | event: string; 22 | name?: string; 23 | value: number; 24 | children?: IcicleEventNode[]; 25 | }; 26 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-icicle-event/src/IcicleEventViz.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import React, { PureComponent } from 'react'; 20 | import memoizeOne from 'memoize-one'; 21 | import { IcicleEventNode } from './IcicleEventNode'; 22 | import IcicleEventChart from './IcicleEventChart'; 23 | import { createPartitionAndLayout } from './utils/IcicleEventTreeHelpers'; 24 | 25 | const memoizedCreatePartitionAndLayout = memoizeOne(createPartitionAndLayout); 26 | 27 | interface Props { 28 | className?: string; 29 | width: number; 30 | height: number; 31 | data: IcicleEventNode; 32 | color: (name: string) => string; 33 | isVertical: boolean; 34 | rounding: number; 35 | transitionDuration: number; 36 | } 37 | 38 | export default class IcicleEventViz extends PureComponent { 39 | render() { 40 | const { data, isVertical, width, height, rounding, transitionDuration } = this.props; 41 | 42 | // Memoized to prevent the creation of a new tree with every render 43 | const root = memoizedCreatePartitionAndLayout( 44 | data, 45 | isVertical ? width : height, 46 | isVertical ? height : width, 47 | ); 48 | 49 | return ( 50 |
51 | 59 |
60 | ); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-icicle-event/src/createMetadata.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { t } from '@superset-ui/translation'; 20 | import { ChartMetadata } from '@superset-ui/chart'; 21 | import thumbnail from './images/thumbnail.png'; 22 | 23 | export default function createMetadata(useLegacyApi = false) { 24 | return new ChartMetadata({ 25 | description: '', 26 | name: t('Icicle Event Chart'), 27 | thumbnail, 28 | useLegacyApi, 29 | }); 30 | } 31 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-icicle-event/src/images/thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache-superset/superset-ui-plugins/75fd10c9c82cec17608be820b03f924be0b5786e/packages/superset-ui-plugin-chart-icicle-event/src/images/thumbnail.png -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-icicle-event/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { ChartPlugin } from '@superset-ui/chart'; 20 | import createMetadata from './createMetadata'; 21 | import transformProps from './transformProps'; 22 | 23 | export default class IcicleEventVizPlugin extends ChartPlugin { 24 | constructor() { 25 | super({ 26 | loadChart: () => import('./IcicleEventViz'), 27 | metadata: createMetadata(), 28 | transformProps, 29 | }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-icicle-event/src/transformProps.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { ChartProps } from '@superset-ui/chart'; 20 | import { findDepth } from './utils/IcicleEventTreeHelpers'; 21 | 22 | export default function transformProps(chartProps: ChartProps) { 23 | const { formData, queryData, width } = chartProps; 24 | // Need to double check if actually part of formData 25 | const { color, isVertical, rounding, transitionDuration } = formData; 26 | const { data } = queryData; 27 | 28 | const chartPropsHeight = chartProps.height; 29 | const rectHeight = 30; 30 | const heightFromTreeDepth = findDepth(data) * rectHeight; 31 | const height = chartPropsHeight > heightFromTreeDepth ? chartPropsHeight : heightFromTreeDepth; 32 | 33 | return { 34 | color, 35 | data, 36 | height, 37 | isVertical, 38 | rounding, 39 | transitionDuration, 40 | width, 41 | }; 42 | } 43 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-icicle-event/src/utils/IcicleEventTreeHelpers.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { max as d3Max } from 'd3-array'; 20 | import { 21 | HierarchyNode, 22 | HierarchyRectangularNode, 23 | hierarchy as d3Hierarchy, 24 | partition as d3Partition, 25 | } from 'd3-hierarchy'; 26 | import { IcicleEventNode } from '../IcicleEventNode'; 27 | 28 | export function findDepth(node: IcicleEventNode, depth: number = 0): number { 29 | if (!node.children) { 30 | return depth; 31 | } 32 | 33 | const maxDepth = d3Max(node.children.map(child => findDepth(child, depth + 1))); 34 | 35 | return maxDepth ?? depth; 36 | } 37 | 38 | export function hierarchySort( 39 | a: HierarchyNode, 40 | b: HierarchyNode, 41 | ): number { 42 | if (a?.value && b?.value) { 43 | return b.value - a.value || b.height - a.height; 44 | } 45 | 46 | return 0; 47 | } 48 | 49 | export function createPartitionAndLayout( 50 | data: IcicleEventNode, 51 | width: number, 52 | height: number, 53 | ): HierarchyRectangularNode { 54 | const root = d3Hierarchy(data).sort(hierarchySort); 55 | const createLayout = d3Partition().size([width, height]); 56 | const layout = createLayout(root); 57 | 58 | return layout; 59 | } 60 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-icicle-event/src/utils/RenderedIcicleAccessors.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { HierarchyRectangularNode } from 'd3-hierarchy'; 20 | import { IcicleEventNode } from '../IcicleEventNode'; 21 | 22 | export function x0(isVertical: boolean, d: HierarchyRectangularNode) { 23 | return isVertical ? d.y0 : d.x0; 24 | } 25 | 26 | export function x1(isVertical: boolean, d: HierarchyRectangularNode) { 27 | return isVertical ? d.y1 : d.x1; 28 | } 29 | 30 | export function y0(isVertical: boolean, d: HierarchyRectangularNode) { 31 | return isVertical ? d.x0 : d.y0; 32 | } 33 | 34 | export function y1(isVertical: boolean, d: HierarchyRectangularNode) { 35 | return isVertical ? d.x1 : d.y1; 36 | } 37 | 38 | export function rectWidth( 39 | isVertical: boolean, 40 | boxMargin: { x: number; y: number }, 41 | d: HierarchyRectangularNode, 42 | ) { 43 | return Math.max(0, y1(isVertical, d) - y0(isVertical, d) - boxMargin.y * 2); 44 | } 45 | 46 | export function rectHeight( 47 | isVertical: boolean, 48 | boxMargin: { x: number; y: number }, 49 | d: HierarchyRectangularNode, 50 | ) { 51 | return Math.max( 52 | 0, 53 | x1(isVertical, d) - 54 | x0(isVertical, d) - 55 | (Math.min(1, (x1(isVertical, d) - x0(isVertical, d)) / 2) + boxMargin.x * 2), 56 | ); 57 | } 58 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-icicle-event/test/utils/IcicleEventTreeHelpers.test.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { HierarchyNode, HierarchyRectangularNode, hierarchy as d3Hierarchy } from 'd3-hierarchy'; 20 | import { IcicleEventNode } from '../../src/IcicleEventNode'; 21 | import { 22 | findDepth, 23 | hierarchySort, 24 | createPartitionAndLayout, 25 | } from '../../src/utils/IcicleEventTreeHelpers'; 26 | 27 | const ROOT_NODE: IcicleEventNode = { 28 | id: 'root', 29 | event: 'root', 30 | name: 'Root', 31 | value: 1, 32 | }; 33 | 34 | const NODE_A: IcicleEventNode = { 35 | id: 'a-0', 36 | event: 'a', 37 | name: 'A', 38 | value: 1, 39 | }; 40 | 41 | const NODE_B: IcicleEventNode = { 42 | id: 'b-0', 43 | event: 'b', 44 | name: 'B', 45 | value: 2, 46 | }; 47 | 48 | const BALANCED_TREE: IcicleEventNode = { 49 | id: 'root', 50 | event: 'root', 51 | name: 'Root', 52 | value: 3, 53 | children: [NODE_A, NODE_B], 54 | }; 55 | 56 | const UNBALANCED_TREE: IcicleEventNode = { 57 | id: 'root', 58 | event: 'root', 59 | name: 'Root', 60 | value: 2, 61 | children: [ 62 | { 63 | id: 'a-1', 64 | event: 'a', 65 | name: 'A', 66 | value: 2, 67 | children: [NODE_B], 68 | }, 69 | ], 70 | }; 71 | 72 | describe('findDepth', () => { 73 | it('finds depth of tree with root node', () => { 74 | expect(findDepth(ROOT_NODE)).toBe(0); 75 | }); 76 | 77 | it('finds depth of a balanced tree', () => { 78 | expect(findDepth(BALANCED_TREE)).toBe(1); 79 | }); 80 | 81 | it('finds depth of an unbalanced tree', () => { 82 | expect(findDepth(UNBALANCED_TREE)).toBe(2); 83 | }); 84 | }); 85 | 86 | describe('hierarchySort', () => { 87 | it('sorts D3 hierarchy nodes correctly', () => { 88 | const root: HierarchyNode = d3Hierarchy(BALANCED_TREE).sort(hierarchySort); 89 | expect(root.children).toHaveLength(2); 90 | expect(root.children![0].data.id).toBe('b-0'); 91 | }); 92 | }); 93 | 94 | describe('createPartitionAndLayout', () => { 95 | it('creates a D3 partition and returns the Hierarchy Rectangular Node correctly', () => { 96 | const root: HierarchyRectangularNode = createPartitionAndLayout( 97 | BALANCED_TREE, 98 | 100, 99 | 100, 100 | ); 101 | expect(root).toHaveProperty('x0', 0); 102 | expect(root).toHaveProperty('y0', 0); 103 | expect(root).toHaveProperty('x1', 100); 104 | expect(root).toHaveProperty('y1', 50); 105 | 106 | expect(root.children).toHaveLength(2); 107 | 108 | const child = root.children![0]; 109 | expect(child).toHaveProperty('x0', 0); 110 | expect(child).toHaveProperty('y0', 50); 111 | expect(child).toHaveProperty('x1'); 112 | // 2/3 since NODE_B has a value of 2 & sibling has value of 1 113 | expect(child.x1).toBeCloseTo(100 * (2 / 3), 5); 114 | expect(child).toHaveProperty('y1', 100); 115 | }); 116 | }); 117 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-icicle-event/types/external.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | declare module '*.png' { 20 | const value: any; 21 | export default value; 22 | } 23 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-table/README.md: -------------------------------------------------------------------------------- 1 | ## @superset-ui/plugin-chart-table 2 | 3 | [![Version](https://img.shields.io/npm/v/@superset-ui/plugin-chart-table.svg?style=flat-square)](https://img.shields.io/npm/v/@superset-ui/plugin-chart-table.svg?style=flat-square) 4 | [![David (path)](https://img.shields.io/david/apache-superset/superset-ui-plugins.svg?path=packages%2Fsuperset-ui-plugin-chart-table&style=flat-square)](https://david-dm.org/apache-superset/superset-ui-plugins?path=packages/superset-ui-plugin-chart-table) 5 | 6 | This plugin provides Table for Superset. 7 | 8 | ### Usage 9 | 10 | Configure `key`, which can be any `string`, and register the plugin. This `key` will be used to lookup this chart throughout the app. 11 | 12 | ```js 13 | import TableChartPlugin from '@superset-ui/plugin-chart-table'; 14 | 15 | new TableChartPlugin() 16 | .configure({ key: 'table' }) 17 | .register(); 18 | ``` 19 | 20 | Then use it via `SuperChart`. See [storybook](https://apache-superset.github.io/superset-ui-plugins/?selectedKind=plugin-chart-table) for more details. 21 | 22 | ```js 23 | 32 | ``` -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-table/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@superset-ui/plugin-chart-table", 3 | "version": "0.11.15", 4 | "description": "Superset Chart - Table", 5 | "sideEffects": false, 6 | "main": "lib/index.js", 7 | "module": "esm/index.js", 8 | "files": [ 9 | "esm", 10 | "lib" 11 | ], 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/apache-superset/superset-ui-plugins.git" 15 | }, 16 | "keywords": [ 17 | "superset" 18 | ], 19 | "author": "Superset", 20 | "license": "Apache-2.0", 21 | "bugs": { 22 | "url": "https://github.com/apache-superset/superset-ui-plugins/issues" 23 | }, 24 | "homepage": "https://github.com/apache-superset/superset-ui-plugins#readme", 25 | "publishConfig": { 26 | "access": "public" 27 | }, 28 | "dependencies": { 29 | "@airbnb/lunar": "^2.35.0", 30 | "@airbnb/lunar-icons": "^2.1.4", 31 | "@types/dompurify": "^2.0.0", 32 | "dompurify": "^2.0.6", 33 | "reselect": "^4.0.0" 34 | }, 35 | "peerDependencies": { 36 | "@superset-ui/chart": "^0.12.0", 37 | "@superset-ui/number-format": "^0.12.0", 38 | "@superset-ui/query": "^0.12.0", 39 | "@superset-ui/time-format": "^0.12.0", 40 | "@superset-ui/translation": "^0.12.0", 41 | "react": "^16.8.6" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-table/src/Table.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import DataTable from '@airbnb/lunar/lib/components/DataTable'; 3 | import Text from '@airbnb/lunar/lib/components/Text'; 4 | import Input from '@airbnb/lunar/lib/components/Input'; 5 | import withStyles, { WithStylesProps } from '@airbnb/lunar/lib/composers/withStyles'; 6 | import { 7 | Renderers, 8 | ParentRow, 9 | ColumnMetadata, 10 | GenericRow, 11 | } from '@airbnb/lunar/lib/components/DataTable/types'; 12 | import { createSelector } from 'reselect'; 13 | import { TimeFormatter } from '@superset-ui/time-format'; 14 | import { NumberFormatter } from '@superset-ui/number-format'; 15 | import getRenderer, { ColumnType, Cell } from './getRenderer'; 16 | 17 | type Props = { 18 | data: ParentRow[]; 19 | height: number; 20 | width: number; 21 | alignPositiveNegative?: boolean; 22 | colorPositiveNegative?: boolean; 23 | columns: ColumnType[]; 24 | filters?: { 25 | [key: string]: any[]; 26 | }; 27 | includeSearch?: boolean; 28 | onAddFilter?: (key: string, value: number[]) => void; 29 | onRemoveFilter?: (key: string, value: number[]) => void; 30 | tableFilter: boolean; 31 | }; 32 | 33 | const NOOP = () => {}; 34 | 35 | const defaultProps = { 36 | alignPositiveNegative: false, 37 | colorPositiveNegative: false, 38 | filters: {}, 39 | includeSearch: false, 40 | onAddFilter: NOOP, 41 | onRemoveFilter: NOOP, 42 | }; 43 | 44 | const SEARCH_BAR_HEIGHT = 40; 45 | 46 | const CHAR_WIDTH = 10; 47 | 48 | const CELL_PADDING = 32; 49 | 50 | const MAX_COLUMN_WIDTH = 300; 51 | 52 | const htmlTagRegex = /(<([^>]+)>)/gi; 53 | 54 | export type TableProps = Props & Readonly; 55 | 56 | type InternalTableProps = TableProps & WithStylesProps; 57 | 58 | type TableState = { 59 | selectedCells: Set; 60 | searchKeyword: string; 61 | filteredRows: ParentRow[]; 62 | filters: { 63 | [key: string]: (string | number)[]; 64 | }; 65 | }; 66 | 67 | function getCellHash(cell: Cell) { 68 | return `${cell.key}#${cell.value}`; 69 | } 70 | 71 | function getText(value: unknown, format: TimeFormatter | NumberFormatter | undefined) { 72 | if (format) { 73 | return format.format(value as any); 74 | } 75 | if (typeof value === 'string') { 76 | return value.replace(htmlTagRegex, ''); 77 | } 78 | 79 | return String(value); 80 | } 81 | 82 | type columnWidthMetaDataType = { 83 | [key: string]: { 84 | maxWidth: number; 85 | width: number; 86 | }; 87 | }; 88 | 89 | class TableVis extends React.PureComponent { 90 | columnWidthSelector = createSelector( 91 | (data: { rows: ParentRow[]; columns: ColumnType[] }) => data, 92 | data => { 93 | const { rows, columns } = data; 94 | const keys = rows && rows.length > 0 ? Object.keys(rows[0].data) : []; 95 | let totalWidth = 0; 96 | const columnWidthMetaData: columnWidthMetaDataType = {}; 97 | const columnsMap: { 98 | [key: string]: ColumnType; 99 | } = {}; 100 | 101 | columns.forEach(column => { 102 | columnsMap[column.key] = column; 103 | }); 104 | 105 | keys.forEach(key => { 106 | const column = columnsMap[key]; 107 | const format = column?.format; 108 | const maxLength = Math.max( 109 | ...rows.map(d => getText(d.data[key], format).length), 110 | key.length, 111 | ); 112 | const stringWidth = maxLength * CHAR_WIDTH + CELL_PADDING; 113 | columnWidthMetaData[key] = { 114 | maxWidth: MAX_COLUMN_WIDTH, 115 | width: stringWidth, 116 | }; 117 | totalWidth += Math.min(stringWidth, MAX_COLUMN_WIDTH); 118 | }); 119 | 120 | return { 121 | columnWidthMetaData, 122 | totalWidth, 123 | }; 124 | }, 125 | ); 126 | 127 | static defaultProps = defaultProps; 128 | 129 | constructor(props: InternalTableProps) { 130 | super(props); 131 | this.state = { 132 | filteredRows: [], 133 | // eslint-disable-next-line react/no-unused-state 134 | filters: props.filters, 135 | searchKeyword: '', 136 | selectedCells: new Set(), 137 | }; 138 | } 139 | 140 | static getDerivedStateFromProps: React.GetDerivedStateFromProps< 141 | InternalTableProps, 142 | TableState 143 | > = (props: InternalTableProps, state: TableState) => { 144 | const { filters } = props; 145 | const { selectedCells, filters: prevFilters } = state; 146 | if (prevFilters !== filters) { 147 | const newSelectedCells = new Set(Array.from(selectedCells)); 148 | Object.keys(filters).forEach(key => { 149 | filters[key].forEach(value => { 150 | newSelectedCells.add( 151 | getCellHash({ 152 | key, 153 | value, 154 | }), 155 | ); 156 | }); 157 | }); 158 | 159 | return { 160 | ...state, 161 | filters, 162 | selectedCells: newSelectedCells, 163 | }; 164 | } 165 | 166 | return state; 167 | }; 168 | 169 | handleCellSelected = (cell: Cell) => () => { 170 | const { selectedCells } = this.state; 171 | const { tableFilter, onRemoveFilter, onAddFilter } = this.props; 172 | 173 | if (!tableFilter) { 174 | return; 175 | } 176 | const newSelectedCells = new Set(Array.from(selectedCells)); 177 | const cellHash = getCellHash(cell); 178 | if (newSelectedCells.has(cellHash)) { 179 | newSelectedCells.delete(cellHash); 180 | onRemoveFilter(cell.key, [cell.value as number]); 181 | } else { 182 | newSelectedCells.add(cellHash); 183 | onAddFilter(cell.key, [cell.value as number]); 184 | } 185 | this.setState({ 186 | selectedCells: newSelectedCells, 187 | }); 188 | }; 189 | 190 | isSelected = (cell: Cell) => { 191 | const { selectedCells } = this.state; 192 | 193 | return selectedCells.has(getCellHash(cell)); 194 | }; 195 | 196 | handleSearch = (value: string) => { 197 | const { searchKeyword } = this.state; 198 | const { data } = this.props; 199 | if (searchKeyword !== value) { 200 | const filteredRows = data.filter(row => { 201 | const content = Object.keys(row.data) 202 | .map(key => row.data[key]) 203 | .join('|') 204 | .toLowerCase(); 205 | 206 | return content.includes(value.toLowerCase()); 207 | }); 208 | this.setState({ 209 | filteredRows, 210 | searchKeyword: value, 211 | }); 212 | } 213 | }; 214 | 215 | render() { 216 | const { 217 | cx, 218 | data, 219 | columns, 220 | alignPositiveNegative, 221 | colorPositiveNegative, 222 | height, 223 | width, 224 | tableFilter, 225 | styles, 226 | includeSearch, 227 | } = this.props; 228 | 229 | const { filteredRows, searchKeyword } = this.state; 230 | 231 | const dataToRender = searchKeyword === '' ? data : filteredRows; 232 | const renderers: Renderers = {}; 233 | const columnMetadata: ColumnMetadata = {}; 234 | const convertToLowerCase = ({ data: d }: GenericRow, key: string) => 235 | typeof d[key] === 'string' ? (d[key] as string).toLowerCase() : d[key]; 236 | 237 | columns.forEach(column => { 238 | renderers[column.key] = getRenderer({ 239 | alignPositiveNegative, 240 | colorPositiveNegative, 241 | column, 242 | enableFilter: tableFilter, 243 | handleCellSelected: this.handleCellSelected, 244 | isSelected: this.isSelected, 245 | }); 246 | if (column.type === 'metric') { 247 | columnMetadata[column.key] = { 248 | rightAlign: 1, 249 | }; 250 | } 251 | }); 252 | 253 | const keys = dataToRender && dataToRender.length > 0 ? Object.keys(dataToRender[0].data) : []; 254 | const columnWidthInfo = this.columnWidthSelector({ columns, rows: data }); 255 | 256 | keys.forEach(key => { 257 | columnMetadata[key] = { 258 | ...columnWidthInfo.columnWidthMetaData[key], 259 | ...columnMetadata[key], 260 | }; 261 | 262 | if (!renderers[key]) { 263 | renderers[key] = getRenderer({ 264 | alignPositiveNegative, 265 | colorPositiveNegative, 266 | column: { 267 | key, 268 | label: key, 269 | type: 'string', 270 | }, 271 | enableFilter: tableFilter, 272 | handleCellSelected: this.handleCellSelected, 273 | isSelected: this.isSelected, 274 | }); 275 | } 276 | }); 277 | 278 | const tableHeight = includeSearch ? height - SEARCH_BAR_HEIGHT : height; 279 | 280 | return ( 281 | <> 282 | {includeSearch && ( 283 |
284 |
285 | 293 |
294 | 295 | Showing {dataToRender.length}/{data.length} rows 296 | 297 |
298 | )} 299 |
300 | 312 |
313 | 314 | ); 315 | } 316 | } 317 | 318 | export default withStyles(({ unit }) => ({ 319 | container: { 320 | display: 'grid', 321 | overflowX: 'scroll', 322 | }, 323 | searchBar: { 324 | alignItems: 'baseline', 325 | display: 'flex', 326 | flexDirection: 'row-reverse', 327 | flexGrow: 0, 328 | marginBottom: unit, 329 | }, 330 | searchBox: { 331 | marginLeft: unit, 332 | width: 25 * unit, 333 | }, 334 | }))(TableVis); 335 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-table/src/TableFormData.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable camelcase */ 2 | import { QueryFormData, QueryFormDataMetric } from '@superset-ui/query'; 3 | 4 | type TableFormData = QueryFormData & { 5 | all_columns: string[]; 6 | percent_metrics: QueryFormDataMetric[]; 7 | include_time: boolean; 8 | order_by_cols: string[]; 9 | }; 10 | 11 | // eslint-disable-next-line no-undef 12 | export default TableFormData; 13 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-table/src/buildQuery.ts: -------------------------------------------------------------------------------- 1 | import { 2 | buildQueryContext, 3 | convertMetric, 4 | QueryFormDataMetric, 5 | QueryObjectMetric, 6 | } from '@superset-ui/query'; 7 | import TableFormData from './TableFormData'; 8 | 9 | export default function buildQuery(formData: TableFormData) { 10 | // Set the single QueryObject's groupby field with series in formData 11 | return buildQueryContext(formData, baseQueryObject => { 12 | const isTimeseries = formData.include_time; 13 | let columns: string[] = []; 14 | let { groupby } = baseQueryObject; 15 | const orderby: [QueryObjectMetric, boolean][] = []; 16 | const sortby = formData.timeseries_limit_metric; 17 | if (formData.all_columns && formData.all_columns.length > 0) { 18 | columns = [...formData.all_columns]; 19 | const orderByColumns = formData.order_by_cols || []; 20 | orderByColumns.forEach(columnOrder => { 21 | const parsedColumnOrder: [QueryFormDataMetric, boolean] = JSON.parse(columnOrder); 22 | orderby.push([convertMetric(parsedColumnOrder[0]), parsedColumnOrder[1]]); 23 | }); 24 | groupby = []; 25 | } else if (sortby) { 26 | orderby.push([convertMetric(sortby), !formData.order_desc]); 27 | } 28 | 29 | return [ 30 | { 31 | ...baseQueryObject, 32 | columns, 33 | groupby, 34 | is_timeseries: isTimeseries, 35 | orderby, 36 | }, 37 | ]; 38 | }); 39 | } 40 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-table/src/components/HTMLRenderer.tsx: -------------------------------------------------------------------------------- 1 | import React, { useMemo } from 'react'; 2 | import dompurify from 'dompurify'; 3 | 4 | const isHTML = RegExp.prototype.test.bind(/(<([^>]+)>)/i); 5 | 6 | export default function HTMLRenderer({ value }: { value: string }) { 7 | if (isHTML(value)) { 8 | // eslint-disable-next-line react-hooks/rules-of-hooks 9 | const html = useMemo(() => ({ __html: dompurify.sanitize(value) }), [value]); 10 | return ( 11 | // eslint-disable-next-line react/no-danger 12 |
13 | ); 14 | } 15 | 16 | // eslint-disable-next-line react/jsx-no-useless-fragment 17 | return <>{value}; 18 | } 19 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-table/src/createMetadata.ts: -------------------------------------------------------------------------------- 1 | import { t } from '@superset-ui/translation'; 2 | import { ChartMetadata } from '@superset-ui/chart'; 3 | import thumbnail from './images/thumbnail.png'; 4 | 5 | export default function createMetadata(useLegacyApi = false) { 6 | return new ChartMetadata({ 7 | canBeAnnotationTypes: ['EVENT', 'INTERVAL'], 8 | description: '', 9 | name: t('Table'), 10 | thumbnail, 11 | useLegacyApi, 12 | }); 13 | } 14 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-table/src/getRenderer.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable jsx-a11y/no-static-element-interactions */ 2 | /* eslint-disable jsx-a11y/click-events-have-key-events */ 3 | import React, { CSSProperties, useMemo } from 'react'; 4 | import { HEIGHT_TO_PX } from '@airbnb/lunar/lib/components/DataTable/constants'; 5 | import { RendererProps } from '@airbnb/lunar/lib/components/DataTable/types'; 6 | import { NumberFormatter } from '@superset-ui/number-format'; 7 | import { TimeFormatter } from '@superset-ui/time-format'; 8 | import HTMLRenderer from './components/HTMLRenderer'; 9 | 10 | const NEGATIVE_COLOR = '#FFA8A8'; 11 | const POSITIVE_COLOR = '#ced4da'; 12 | const SELECTION_COLOR = '#EBEBEB'; 13 | 14 | const NOOP = () => {}; 15 | 16 | const HEIGHT = HEIGHT_TO_PX.micro; 17 | 18 | export type ColumnType = { 19 | key: string; 20 | label: string; 21 | format?: NumberFormatter | TimeFormatter | undefined; 22 | type: 'metric' | 'string'; 23 | maxValue?: number; 24 | minValue?: number; 25 | }; 26 | 27 | export type Cell = { 28 | key: string; 29 | value: any; 30 | }; 31 | 32 | const NUMBER_STYLE: CSSProperties = { 33 | marginLeft: 'auto', 34 | marginRight: '4px', 35 | zIndex: 10, 36 | }; 37 | 38 | export default function getRenderer({ 39 | column, 40 | alignPositiveNegative, 41 | colorPositiveNegative, 42 | enableFilter, 43 | isSelected, 44 | handleCellSelected, 45 | }: { 46 | column: ColumnType; 47 | alignPositiveNegative: boolean; 48 | colorPositiveNegative: boolean; 49 | enableFilter: boolean; 50 | isSelected: (cell: Cell) => boolean; 51 | handleCellSelected: (cell: Cell) => (...args: any[]) => void; 52 | }) { 53 | const { format, type } = column; 54 | 55 | const isMetric = type === 'metric'; 56 | const cursorStyle = enableFilter && !isMetric ? 'pointer' : 'default'; 57 | 58 | const boxContainerStyle: CSSProperties = { 59 | alignItems: 'center', 60 | display: 'flex', 61 | margin: '0px 16px', 62 | position: 'relative', 63 | textAlign: isMetric ? 'right' : 'left', 64 | }; 65 | 66 | const baseBoxStyle: CSSProperties = { 67 | cursor: cursorStyle, 68 | margin: '4px -16px', 69 | wordBreak: 'break-all', 70 | }; 71 | 72 | const selectedBoxStyle: CSSProperties = { 73 | ...baseBoxStyle, 74 | backgroundColor: SELECTION_COLOR, 75 | }; 76 | 77 | const getBoxStyle = enableFilter 78 | ? (selected: boolean) => (selected ? selectedBoxStyle : baseBoxStyle) 79 | : () => baseBoxStyle; 80 | 81 | const posExtent = Math.abs(Math.max(column.maxValue!, 0)); 82 | const negExtent = Math.abs(Math.min(column.minValue!, 0)); 83 | const total = posExtent + negExtent; 84 | 85 | return ({ keyName, row }: RendererProps) => { 86 | const value = row.rowData.data[keyName]; 87 | const cell = { key: keyName as string, value }; 88 | const handleClick = isMetric ? NOOP : useMemo(() => handleCellSelected(cell), [cell]); 89 | 90 | let Parent; 91 | if (isMetric) { 92 | let left = 0; 93 | let width = 0; 94 | const numericValue = value as number; 95 | if (alignPositiveNegative) { 96 | width = Math.abs( 97 | Math.round((numericValue / Math.max(column.maxValue!, Math.abs(column.minValue!))) * 100), 98 | ); 99 | } else { 100 | left = Math.round((Math.min(negExtent + numericValue, negExtent) / total) * 100); 101 | width = Math.round((Math.abs(numericValue) / total) * 100); 102 | } 103 | const color = colorPositiveNegative && numericValue < 0 ? NEGATIVE_COLOR : POSITIVE_COLOR; 104 | 105 | Parent = ({ children }: { children: React.ReactNode }) => { 106 | const barStyle: CSSProperties = { 107 | background: color, 108 | borderRadius: 3, 109 | height: HEIGHT / 2 + 4, 110 | left: `${left}%`, 111 | position: 'absolute', 112 | width: `${width}%`, 113 | }; 114 | 115 | return ( 116 | <> 117 |
118 |
{children}
119 | 120 | ); 121 | }; 122 | } else { 123 | Parent = React.Fragment; 124 | } 125 | 126 | return ( 127 |
128 |
129 |
130 | 131 | {format ? ( 132 | format.format(value as number & Date) 133 | ) : ( 134 | 135 | )} 136 | 137 |
138 |
139 |
140 | ); 141 | }; 142 | } 143 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-table/src/images/thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apache-superset/superset-ui-plugins/75fd10c9c82cec17608be820b03f924be0b5786e/packages/superset-ui-plugin-chart-table/src/images/thumbnail.png -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-table/src/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { ChartPlugin } from '@superset-ui/chart'; 20 | import Core from '@airbnb/lunar/lib'; 21 | import transformProps from './transformProps'; 22 | import createMetadata from './createMetadata'; 23 | import buildQuery from './buildQuery'; 24 | import TableFormData from './TableFormData'; 25 | 26 | Core.initialize({ name: 'superset-datatable' }); 27 | const { aesthetic } = Core; 28 | // @ts-ignore 29 | aesthetic.globals = {}; 30 | 31 | export default class TableChartPlugin extends ChartPlugin { 32 | constructor() { 33 | super({ 34 | buildQuery, 35 | loadChart: () => import('./Table'), 36 | metadata: createMetadata(), 37 | transformProps, 38 | }); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-table/src/legacy/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | import { ChartPlugin } from '@superset-ui/chart'; 20 | import Core from '@airbnb/lunar/lib'; 21 | import transformProps from './transformProps'; 22 | import createMetadata from '../createMetadata'; 23 | 24 | Core.initialize({ name: 'superset-datatable' }); 25 | 26 | const { aesthetic } = Core; 27 | // @ts-ignore 28 | aesthetic.globals = {}; 29 | 30 | export default class TableChartPlugin extends ChartPlugin { 31 | constructor() { 32 | super({ 33 | loadChart: () => import('../Table'), 34 | metadata: createMetadata(true), 35 | transformProps, 36 | }); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-table/src/legacy/transformProps.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | import { ChartProps } from '@superset-ui/chart'; 21 | import getProcessColumnsFunction from '../processColumns'; 22 | import getProcessMetricsFunction from '../processMetrics'; 23 | import getProcessDataFunction from '../processData'; 24 | 25 | const processColumns = getProcessColumnsFunction(); 26 | const processMetrics = getProcessMetricsFunction(); 27 | const processData = getProcessDataFunction(); 28 | 29 | const NOOP = () => {}; 30 | 31 | export default function transformProps(chartProps: ChartProps) { 32 | const { height, datasource, initialValues, formData, hooks, queryData, width } = chartProps; 33 | 34 | const { onAddFilter = NOOP } = hooks; 35 | 36 | const { 37 | alignPn, 38 | colorPn, 39 | includeSearch, 40 | metrics: rawMetrics, 41 | orderDesc, 42 | pageLength, 43 | percentMetrics, 44 | tableFilter, 45 | tableTimestampFormat, 46 | timeseriesLimitMetric, 47 | } = formData; 48 | const { records, columns } = queryData.data; 49 | 50 | const metrics = processMetrics({ 51 | metrics: rawMetrics, 52 | percentMetrics, 53 | records, 54 | }); 55 | 56 | const processedData = processData({ 57 | timeseriesLimitMetric, 58 | orderDesc, 59 | records, 60 | metrics, 61 | }); 62 | 63 | const processedColumns = processColumns({ 64 | columns, 65 | metrics, 66 | records, 67 | tableTimestampFormat, 68 | datasource, 69 | }); 70 | 71 | return { 72 | height, 73 | width, 74 | data: processedData, 75 | alignPositiveNegative: alignPn, 76 | colorPositiveNegative: colorPn, 77 | columns: processedColumns, 78 | filters: initialValues, 79 | includeSearch, 80 | onAddFilter, 81 | orderDesc, 82 | pageLength: pageLength && parseInt(pageLength, 10), 83 | tableFilter, 84 | }; 85 | } 86 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-table/src/processColumns.ts: -------------------------------------------------------------------------------- 1 | import { getNumberFormatter, NumberFormats, NumberFormatter } from '@superset-ui/number-format'; 2 | import { getTimeFormatter, TimeFormatter } from '@superset-ui/time-format'; 3 | import { createSelector } from 'reselect'; 4 | import { PlainObject } from './types'; 5 | 6 | const DTTM_ALIAS = '__timestamp'; 7 | 8 | type inputType = { 9 | columns: string[]; 10 | metrics: string[]; 11 | records: any[]; 12 | tableTimestampFormat: string; 13 | datasource: PlainObject; 14 | }; 15 | 16 | function processColumns( 17 | columns: string[], 18 | metrics: string[], 19 | records: any[], 20 | tableTimestampFormat: string, 21 | datasource: PlainObject, 22 | ) { 23 | const { columnFormats, verboseMap } = datasource; 24 | 25 | const dataArray: { 26 | [key: string]: any[]; 27 | } = {}; 28 | 29 | metrics.forEach(metric => { 30 | const arr: any[] = []; 31 | records.forEach(record => { 32 | arr.push(record[metric]); 33 | }); 34 | 35 | dataArray[metric] = arr; 36 | }); 37 | 38 | const maxes: { 39 | [key: string]: number; 40 | } = {}; 41 | const mins: { 42 | [key: string]: number; 43 | } = {}; 44 | 45 | metrics.forEach(metric => { 46 | maxes[metric] = Math.max(...dataArray[metric]); 47 | mins[metric] = Math.min(...dataArray[metric]); 48 | }); 49 | 50 | const formatPercent = getNumberFormatter(NumberFormats.PERCENT_3_POINT); 51 | const tsFormatter = getTimeFormatter(tableTimestampFormat); 52 | 53 | const processedColumns = columns.map((key: string) => { 54 | let label = verboseMap[key]; 55 | const formatString = columnFormats?.[key]; 56 | let formatFunction: NumberFormatter | TimeFormatter | undefined; 57 | let type: 'string' | 'metric' = 'string'; 58 | 59 | if (key === DTTM_ALIAS) { 60 | formatFunction = tsFormatter; 61 | } 62 | 63 | const extraField: { 64 | [key: string]: any; 65 | } = {}; 66 | 67 | if (metrics.includes(key)) { 68 | formatFunction = getNumberFormatter(formatString); 69 | type = 'metric'; 70 | extraField.maxValue = maxes[key]; 71 | extraField.minValue = mins[key]; 72 | } 73 | 74 | // Handle verbose names for percents 75 | if (!label) { 76 | if (key.length > 0 && key[0] === '%') { 77 | const cleanedKey = key.slice(1); 78 | label = `% ${verboseMap[cleanedKey] || cleanedKey}`; 79 | formatFunction = formatPercent; 80 | } else { 81 | label = key; 82 | } 83 | } 84 | 85 | return { 86 | format: formatFunction, 87 | key, 88 | label, 89 | type, 90 | ...extraField, 91 | }; 92 | }); 93 | 94 | return processedColumns; 95 | } 96 | 97 | const getCreateSelectorFunction = () => 98 | createSelector( 99 | (data: inputType) => data.columns, 100 | data => data.metrics, 101 | data => data.records, 102 | data => data.tableTimestampFormat, 103 | data => data.datasource, 104 | (columns, metrics, records, tableTimestampFormat, datasource) => 105 | processColumns(columns, metrics, records, tableTimestampFormat, datasource), 106 | ); 107 | 108 | export default getCreateSelectorFunction; 109 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-table/src/processData.ts: -------------------------------------------------------------------------------- 1 | import { QueryFormDataMetric, AdhocMetric } from '@superset-ui/query'; 2 | import { createSelector } from 'reselect'; 3 | import { PlainObject } from './types'; 4 | 5 | type inputType = { 6 | timeseriesLimitMetric: QueryFormDataMetric; 7 | orderDesc: boolean; 8 | records: PlainObject[]; 9 | metrics: string[]; 10 | }; 11 | 12 | function processData( 13 | timeseriesLimitMetric: QueryFormDataMetric, 14 | orderDesc: boolean, 15 | records: PlainObject[], 16 | metrics: string[], 17 | ) { 18 | const sortByKey = 19 | timeseriesLimitMetric && 20 | ((timeseriesLimitMetric as AdhocMetric).label || (timeseriesLimitMetric as string)); 21 | 22 | let processedRecords = records; 23 | 24 | if (sortByKey) { 25 | processedRecords = records 26 | .slice() 27 | .sort( 28 | orderDesc ? (a, b) => b[sortByKey] - a[sortByKey] : (a, b) => a[sortByKey] - b[sortByKey], 29 | ); 30 | } 31 | 32 | return processedRecords.map( 33 | sortByKey && !metrics.includes(sortByKey) 34 | ? row => { 35 | const data = { ...row }; 36 | delete data[sortByKey]; 37 | 38 | return { data }; 39 | } 40 | : row => ({ data: row }), 41 | ); 42 | } 43 | 44 | const getCreateSelectorFunction = () => 45 | createSelector( 46 | (data: inputType) => data.timeseriesLimitMetric, 47 | data => data.orderDesc, 48 | data => data.records, 49 | data => data.metrics, 50 | (timeseriesLimitMetric, orderDesc, records, metrics) => 51 | processData(timeseriesLimitMetric, orderDesc, records, metrics), 52 | ); 53 | 54 | export default getCreateSelectorFunction; 55 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-table/src/processMetrics.ts: -------------------------------------------------------------------------------- 1 | import { QueryFormDataMetric, AdhocMetric } from '@superset-ui/query'; 2 | import { createSelector } from 'reselect'; 3 | import { PlainObject } from './types'; 4 | 5 | type inputType = { 6 | metrics: QueryFormDataMetric[]; 7 | percentMetrics: QueryFormDataMetric[]; 8 | records: PlainObject[]; 9 | }; 10 | 11 | function processMetrics( 12 | metrics: QueryFormDataMetric[], 13 | percentMetrics: QueryFormDataMetric[], 14 | records: PlainObject[], 15 | ) { 16 | const processedMetrics = (metrics || []).map(m => (m as AdhocMetric).label ?? (m as string)); 17 | 18 | const processedPercentMetrics = (percentMetrics || []) 19 | .map(m => (m as AdhocMetric).label ?? (m as string)) 20 | .map(m => `%${m}`); 21 | 22 | return processedMetrics 23 | .concat(processedPercentMetrics) 24 | .filter(m => typeof records[0][m] === 'number'); 25 | } 26 | 27 | const getCreateSelectorFunction = () => 28 | createSelector( 29 | (data: inputType) => data.metrics, 30 | data => data.percentMetrics, 31 | data => data.records, 32 | (metrics, percentMetrics, records) => processMetrics(metrics, percentMetrics, records), 33 | ); 34 | 35 | export default getCreateSelectorFunction; 36 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-table/src/transformProps.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | import { ChartProps } from '@superset-ui/chart'; 21 | import { QueryFormDataMetric, AdhocMetric } from '@superset-ui/query'; 22 | import getProcessColumnsFunction from './processColumns'; 23 | import getProcessMetricsFunction from './processMetrics'; 24 | import getProcessDataFunction from './processData'; 25 | 26 | const processColumns = getProcessColumnsFunction(); 27 | const processMetrics = getProcessMetricsFunction(); 28 | const processData = getProcessDataFunction(); 29 | 30 | const DTTM_ALIAS = '__timestamp'; 31 | 32 | type PlainObject = { 33 | [key: string]: any; 34 | }; 35 | 36 | function transformData(data: PlainObject[], formData: PlainObject) { 37 | const { groupby = [], metrics = [], allColumns = [] } = formData; 38 | 39 | const columns = new Set( 40 | [...groupby, ...metrics, ...allColumns].map(column => column.label || column), 41 | ); 42 | 43 | let records = data; 44 | 45 | // handle timestamp columns 46 | if (formData.includeTime) { 47 | columns.add(DTTM_ALIAS); 48 | } 49 | 50 | // handle percentage columns. 51 | const percentMetrics: string[] = (formData.percentMetrics || []).map( 52 | (metric: QueryFormDataMetric) => (metric as AdhocMetric).label ?? (metric as string), 53 | ); 54 | 55 | if (percentMetrics.length > 0) { 56 | const sumPercentMetrics = data.reduce((sumMetrics, item) => { 57 | const newSumMetrics = { ...sumMetrics }; 58 | percentMetrics.forEach(metric => { 59 | newSumMetrics[metric] = (sumMetrics[metric] || 0) + (item[metric] || 0); 60 | }); 61 | 62 | return newSumMetrics; 63 | }, {}); 64 | records = data.map(item => { 65 | const newItem = { ...item }; 66 | percentMetrics.forEach(metric => { 67 | newItem[`%${metric}`] = 68 | sumPercentMetrics[metric] === 0 ? null : newItem[metric] / sumPercentMetrics[metric]; 69 | }); 70 | 71 | return newItem; 72 | }); 73 | percentMetrics.forEach(metric => { 74 | columns.add(`%${metric}`); 75 | }); 76 | } 77 | 78 | // handle sortedby column 79 | if (formData.timeseriesLimitMetric) { 80 | const metric = formData.timeseriesLimitMetric.label || formData.timeseriesLimitMetric; 81 | columns.add(metric); 82 | } 83 | 84 | return { 85 | columns: [...columns], 86 | records, 87 | }; 88 | } 89 | 90 | const NOOP = () => {}; 91 | 92 | export default function transformProps(chartProps: ChartProps) { 93 | const { height, width, datasource, initialValues, formData, hooks, queryData } = chartProps; 94 | 95 | const { onAddFilter = NOOP } = hooks; 96 | 97 | const { 98 | alignPn, 99 | colorPn, 100 | includeSearch, 101 | metrics: rawMetrics, 102 | orderDesc, 103 | pageLength, 104 | percentMetrics, 105 | tableFilter, 106 | tableTimestampFormat, 107 | timeseriesLimitMetric, 108 | } = formData; 109 | const { records, columns } = transformData(queryData.data, formData); 110 | 111 | const metrics = processMetrics({ 112 | metrics: rawMetrics, 113 | percentMetrics, 114 | records, 115 | }); 116 | 117 | const processedData = processData({ 118 | metrics, 119 | orderDesc, 120 | records, 121 | timeseriesLimitMetric, 122 | }); 123 | 124 | const processedColumns = processColumns({ 125 | columns, 126 | datasource, 127 | metrics, 128 | records, 129 | tableTimestampFormat, 130 | }); 131 | 132 | return { 133 | alignPositiveNegative: alignPn, 134 | colorPositiveNegative: colorPn, 135 | columns: processedColumns, 136 | data: processedData, 137 | filters: initialValues, 138 | height, 139 | includeSearch, 140 | onAddFilter, 141 | orderDesc, 142 | pageLength: pageLength && parseInt(pageLength, 10), 143 | tableFilter, 144 | width, 145 | }; 146 | } 147 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-table/src/types.ts: -------------------------------------------------------------------------------- 1 | export type PlainObject = { 2 | [key: string]: any; 3 | }; 4 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-table/test/buildQuery.test.ts: -------------------------------------------------------------------------------- 1 | import 'babel-polyfill'; 2 | import buildQuery from '../src/buildQuery'; 3 | 4 | describe('TableVis buildQuery', () => { 5 | const formData = { 6 | datasource: '5__table', 7 | granularity_sqla: 'ds', 8 | series: 'foo', 9 | viz_type: 'table', 10 | all_columns: ['a', 'b', 'c'], 11 | percent_metrics: ['a'], 12 | include_time: false, 13 | order_by_cols: [], 14 | }; 15 | 16 | it('should build groupby with series in form data', () => { 17 | const queryContext = buildQuery(formData); 18 | const [query] = queryContext.queries; 19 | expect(query.metrics![0].label).toEqual('a'); 20 | expect(query.groupby).toHaveLength(0); 21 | }); 22 | }); 23 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-table/test/processData.test.ts: -------------------------------------------------------------------------------- 1 | import getProcessDataFunction from '../src/processData'; 2 | 3 | describe('processData', () => { 4 | const processData = getProcessDataFunction(); 5 | const timeseriesLimitMetric = 'a'; 6 | const orderDesc = true; 7 | const records = [ 8 | { 9 | a: 1, 10 | b: 1, 11 | c: 3, 12 | }, 13 | { 14 | a: 2, 15 | b: 1, 16 | c: 2, 17 | }, 18 | { 19 | a: 3, 20 | b: 1, 21 | c: 1, 22 | }, 23 | ]; 24 | const metrics = ['a', 'b', 'c']; 25 | 26 | it('returns sorted result', () => { 27 | const result = processData({ 28 | timeseriesLimitMetric, 29 | orderDesc, 30 | records, 31 | metrics, 32 | }); 33 | const maxValue = Math.max(...records.map(r => r[timeseriesLimitMetric])); 34 | const minValue = Math.min(...records.map(r => r[timeseriesLimitMetric])); 35 | expect(result[0].data[timeseriesLimitMetric]).toEqual(maxValue); 36 | expect(result[result.length - 1].data[timeseriesLimitMetric]).toEqual(minValue); 37 | }); 38 | 39 | it('removes the timeseriesLimitMetric column if it is not included in metrics', () => { 40 | const filteredMetrics = metrics.filter(metric => metric !== timeseriesLimitMetric); 41 | const result = processData({ 42 | timeseriesLimitMetric, 43 | orderDesc, 44 | records, 45 | metrics: filteredMetrics, 46 | }); 47 | result.forEach(row => { 48 | expect(row.data).toEqual( 49 | expect.not.objectContaining({ 50 | [timeseriesLimitMetric]: expect(Number), 51 | }), 52 | ); 53 | }); 54 | }); 55 | }); 56 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-table/test/processMetrics.test.ts: -------------------------------------------------------------------------------- 1 | import getProcessMetricsFunction from '../src/processMetrics'; 2 | 3 | describe('processData', () => { 4 | const processMetrics = getProcessMetricsFunction(); 5 | const records = [ 6 | { 7 | a: 1, 8 | '%b': 0.4, 9 | c: 3, 10 | }, 11 | { 12 | a: 2, 13 | '%b': 0.4, 14 | c: 2, 15 | }, 16 | { 17 | a: 3, 18 | '%b': 0.2, 19 | c: 1, 20 | }, 21 | ]; 22 | const metrics = ['a']; 23 | const percentMetrics = ['b']; 24 | 25 | it('returns sorted result', () => { 26 | const result = processMetrics({ 27 | records, 28 | metrics, 29 | percentMetrics, 30 | }); 31 | const expected = ['a', '%b']; 32 | expect(result).toEqual(expect.arrayContaining(expected)); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /packages/superset-ui-plugin-chart-table/types/external.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.png'; 2 | -------------------------------------------------------------------------------- /packages/superset-ui-plugins-demo/.storybook/addons.js: -------------------------------------------------------------------------------- 1 | // note that the import order here determines the order in the UI! 2 | import '@storybook/addon-knobs/register'; 3 | import '@storybook/addon-actions/register'; 4 | import '@storybook/addon-links/register'; 5 | import 'storybook-addon-jsx/register'; 6 | -------------------------------------------------------------------------------- /packages/superset-ui-plugins-demo/.storybook/config.js: -------------------------------------------------------------------------------- 1 | import { addParameters, configure } from '@storybook/react'; 2 | 3 | addParameters({ 4 | options: { 5 | name: '@superset-ui/plugins 🔌💡', 6 | addonPanelInRight: false, 7 | enableShortcuts: false, 8 | goFullScreen: false, 9 | hierarchyRootSeparator: null, 10 | hierarchySeparator: /\|/, 11 | selectedAddonPanel: undefined, // The order of addons in the "Addon panel" is the same as you import them in 'addons.js'. The first panel will be opened by default as you run Storybook 12 | showAddonPanel: true, 13 | showSearchBox: false, 14 | showStoriesPanel: true, 15 | sidebarAnimations: true, 16 | sortStoriesByKind: false, 17 | url: '#', 18 | }, 19 | }); 20 | 21 | function loadStorybook() { 22 | require('./storybook.css'); 23 | require('../storybook/stories'); // all of the stories 24 | } 25 | 26 | configure(loadStorybook, module); 27 | -------------------------------------------------------------------------------- /packages/superset-ui-plugins-demo/.storybook/storybook.css: -------------------------------------------------------------------------------- 1 | html, 2 | body, 3 | #root { 4 | height: 100%; 5 | font-family: BlinkMacSystemFont, Roboto, Helvetica Neue, sans-serif; 6 | font-weight: 200; 7 | color: #484848; 8 | } 9 | #root > div { 10 | padding: 8px; 11 | } 12 | 13 | #root > div.superset-body { 14 | background: #f5f5f5; 15 | padding: 16px; 16 | min-height: 100%; 17 | } 18 | #root > div.superset-body .panel { 19 | margin-bottom: 0; 20 | } 21 | -------------------------------------------------------------------------------- /packages/superset-ui-plugins-demo/.storybook/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const TerserPlugin = require('terser-webpack-plugin'); 3 | const webpack = require('webpack'); 4 | 5 | const BABEL_TYPESCRIPT_OPTIONS = { 6 | presets: [ 7 | ['@babel/preset-env', { useBuiltIns: 'entry', corejs: 3 }], 8 | '@babel/preset-react', 9 | '@babel/preset-typescript', 10 | ], 11 | plugins: [ 12 | '@babel/plugin-proposal-object-rest-spread', 13 | '@babel/plugin-proposal-class-properties', 14 | '@babel/plugin-syntax-dynamic-import', 15 | ] 16 | }; 17 | 18 | const SIBLING_PACKAGES_PATH_REGEXP = new RegExp( 19 | `${path.resolve(__dirname, '../../superset-ui-(legacy-)*(plugin|preset)-')}.+/src`, 20 | ); 21 | 22 | module.exports = async ({ config }) => { 23 | config.resolve = config.resolve || {}; 24 | config.resolve.extensions = ['.tsx', '.ts', '.jsx', '.js']; 25 | 26 | // To enable live debugging of other packages when referring to `src` 27 | config.module.rules.push({ 28 | include: SIBLING_PACKAGES_PATH_REGEXP, 29 | exclude: /node_modules/, 30 | test: /\.jsx?$/, 31 | use: config.module.rules[0].use, 32 | }); 33 | 34 | // Enable TypeScript 35 | config.module.rules.push({ 36 | include: SIBLING_PACKAGES_PATH_REGEXP, 37 | exclude: /node_modules/, 38 | test: /\.tsx?$/, 39 | use: [{ 40 | loader: 'babel-loader', 41 | options: BABEL_TYPESCRIPT_OPTIONS, 42 | }], 43 | }); 44 | 45 | config.module.rules.push({ 46 | include: path.resolve(__dirname, '../storybook'), 47 | exclude: /node_modules/, 48 | test: /\.tsx?$/, 49 | use: [{ 50 | loader: 'babel-loader', 51 | options: BABEL_TYPESCRIPT_OPTIONS, 52 | }], 53 | }); 54 | 55 | config.optimization = config.optimization || {}; 56 | config.optimization.splitChunks = { 57 | chunks: 'async' 58 | }; 59 | config.optimization.minimizer = [ 60 | new TerserPlugin({ 61 | parallel: true, 62 | extractComments: true, 63 | }), 64 | ]; 65 | 66 | if (process.env.RUNNING_CONTEXT === 'netlify') { 67 | config.devtool = false; 68 | config.cache = false; 69 | } 70 | 71 | return config; 72 | }; 73 | -------------------------------------------------------------------------------- /packages/superset-ui-plugins-demo/README.md: -------------------------------------------------------------------------------- 1 | ## @superset-ui/demo 2 | 3 | [![David (path)](https://img.shields.io/david/apache-superset/superset-ui-plugins.svg?path=packages%2Fsuperset-ui-demo&style=flat-square)](https://david-dm.org/apache-superset/superset-ui-plugins?path=packages/superset-ui-demo) 4 | 5 | Storybook of `@superset-ui-plugins` packages. See it live at 6 | [apache-superset.github.io/superset-ui-plugins](https://apache-superset.github.io/superset-ui-plugins) 7 | 8 | ### Development 9 | 10 | #### Run storybook 11 | 12 | To view the storybook locally, you should: 13 | 14 | 1. Clone [superset-ui-plugins](https://github.com/apache-superset/superset-ui-plugins) repo. 15 | 2. Run `yarn install && yarn build` in the `superset-ui-plugins` root directory. 16 | 3. Change to the demo directory `cd packages/superset-ui-plugins-demo`. 17 | 4. Run `yarn run storybook`. This will open up a dev server at http://localhost:9001. 18 | 19 | #### Adding new stories 20 | 21 | ###### Existing package 22 | 23 | If stories already exist for the package you are adding, simply extend the `examples` already 24 | exported for that package in the `storybook/stories//index.js` file. 25 | 26 | ###### New package 27 | 28 | If you are creating stories for a package that doesn't yet have any stories, follow these steps: 29 | 30 | 1. Add any new package dependencies via 31 | `yarn add `, but if it is `@superset-ui/*` packages, manually add it to `peerDependencies`. 32 | 33 | 2. Create a new folder that mirrors the package name 34 | 35 | > e.g., `mkdir storybook/stories/superset-ui-color/` 36 | 37 | 3. Add an `index.js` file to that folder with a default export with the following shape: 38 | 39 | > you can use the `|` separator within the `storyPath` string to denote _nested_ stories e.g., 40 | > `storyPath: '@superset-ui/package|Nested i|Nested ii'` 41 | 42 | ```javascript 43 | default export { 44 | examples: [ 45 | { 46 | storyPath: , 47 | storyName: , 48 | renderStory: () => node, 49 | }, 50 | ... 51 | ] 52 | }; 53 | ``` 54 | -------------------------------------------------------------------------------- /packages/superset-ui-plugins-demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@superset-ui/plugins-demo", 3 | "version": "0.11.21", 4 | "description": "Storybook for Superset UI Plugins 🔌💡", 5 | "private": true, 6 | "main": "index.js", 7 | "scripts": { 8 | "demo:clean": "rm -rf _gh-pages", 9 | "demo:build": "build-storybook -o _gh-pages", 10 | "demo:publish": "gh-pages -d _gh-pages", 11 | "deploy-demo": "npm run demo:clean && npm run demo:build && npm run demo:publish && npm run demo:clean", 12 | "storybook:run": "start-storybook -p 9001", 13 | "storybook": "cd ../../ && yarn build && cd ./packages/superset-ui-plugins-demo && yarn storybook:run" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/apache-superset/superset-ui-plugins.git" 18 | }, 19 | "keywords": [ 20 | "storybook", 21 | "superset", 22 | "ui", 23 | "visualization", 24 | "analysis", 25 | "data" 26 | ], 27 | "license": "Apache-2.0", 28 | "bugs": { 29 | "url": "https://github.com/apache-superset/superset-ui-plugins/issues" 30 | }, 31 | "homepage": "https://github.com/apache-superset/superset-ui-plugins#readme", 32 | "dependencies": { 33 | "@babel/polyfill": "^7.4.3", 34 | "@data-ui/event-flow": "^0.0.84", 35 | "@storybook/addon-actions": "^5.0.9", 36 | "@storybook/addon-knobs": "^5.0.9", 37 | "@storybook/addon-links": "^5.0.9", 38 | "@storybook/addons": "^5.0.9", 39 | "@storybook/react": "^5.0.9", 40 | "@types/react": "^16.8.8", 41 | "@types/storybook__react": "4.0.2", 42 | "bootstrap": "^3.4.1", 43 | "jquery": "^3.4.1", 44 | "react": "^16.6.0", 45 | "storybook-addon-jsx": "^7.1.0" 46 | }, 47 | "devDependencies": { 48 | "@babel/core": "^7.4.3", 49 | "@babel/plugin-syntax-dynamic-import": "^7.2.0", 50 | "babel-loader": "^8.0.5", 51 | "gh-pages": "^2.0.1", 52 | "terser-webpack-plugin": "2.3.5" 53 | }, 54 | "peerDependencies": { 55 | "@superset-ui/chart": "^0.12.0", 56 | "@superset-ui/chart-composition": "^0.12.0", 57 | "@superset-ui/color": "^0.12.0", 58 | "@superset-ui/connection": "^0.12.0", 59 | "@superset-ui/number-format": "^0.12.10", 60 | "@superset-ui/time-format": "^0.12.0", 61 | "@superset-ui/translation": "^0.12.0" 62 | } 63 | } -------------------------------------------------------------------------------- /packages/superset-ui-plugins-demo/storybook/shared/components/ErrorMessage.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export type Props = { 4 | error: Error; 5 | }; 6 | 7 | export default function ErrorMessage({ error }: Props) { 8 | return ( 9 |
10 | {error.stack || error.message} 11 | {!error.message && 12 | !error.stack && 13 | (typeof error === 'object' ? JSON.stringify(error) : String(error))} 14 |
15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /packages/superset-ui-plugins-demo/storybook/shared/components/Expandable.tsx: -------------------------------------------------------------------------------- 1 | import React, { ReactNode } from 'react'; 2 | 3 | export type Props = { 4 | children: ReactNode; 5 | expandableWhat?: string; 6 | }; 7 | 8 | type State = { 9 | open: boolean; 10 | }; 11 | 12 | export default class Expandable extends React.Component { 13 | constructor(props: Props) { 14 | super(props); 15 | this.state = { open: false }; 16 | this.handleToggle = this.handleToggle.bind(this); 17 | } 18 | 19 | handleToggle() { 20 | this.setState(({ open }) => ({ open: !open })); 21 | } 22 | 23 | render() { 24 | const { open } = this.state; 25 | const { children, expandableWhat } = this.props; 26 | 27 | return ( 28 |
29 | 36 |
37 |
38 | {open ? children : null} 39 |
40 | ); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/superset-ui-plugins-demo/storybook/shared/components/VerifyCORS.tsx: -------------------------------------------------------------------------------- 1 | import React, { ReactNode } from 'react'; 2 | import { SupersetClient } from '@superset-ui/connection'; 3 | import ErrorMessage from './ErrorMessage'; 4 | 5 | export type Props = { 6 | children: ({ payload }: { payload?: object }) => ReactNode; 7 | endpoint?: string; 8 | host: string; 9 | method?: 'POST' | 'GET'; 10 | postPayload?: string; 11 | }; 12 | 13 | type State = { 14 | didVerify: boolean; 15 | error?: Error; 16 | payload?: object; 17 | }; 18 | 19 | export const renderError = (error: Error) => ( 20 |
21 | The following error occurred, make sure you have
22 | 1) configured CORS in Superset to receive requests from this domain.
23 | 2) set the Superset host correctly below.
24 | 3) debug the CORS configuration under the `@superset-ui/connection` stories. 25 |
26 |
27 | 28 |
29 | ); 30 | 31 | export default class VerifyCORS extends React.Component { 32 | constructor(props: Props) { 33 | super(props); 34 | this.state = { didVerify: false }; 35 | this.handleVerify = this.handleVerify.bind(this); 36 | } 37 | 38 | componentDidUpdate(prevProps: Props) { 39 | const { endpoint, host, postPayload, method } = this.props; 40 | if ( 41 | (this.state.didVerify || this.state.error) && 42 | (prevProps.endpoint !== endpoint || 43 | prevProps.host !== host || 44 | prevProps.postPayload !== postPayload || 45 | prevProps.method !== method) 46 | ) { 47 | // eslint-disable-next-line react/no-did-update-set-state 48 | this.setState({ didVerify: false, error: undefined }); 49 | } 50 | } 51 | 52 | handleVerify() { 53 | const { endpoint, host, postPayload, method } = this.props; 54 | 55 | SupersetClient.reset(); 56 | 57 | SupersetClient.configure({ 58 | credentials: 'include', 59 | host, 60 | mode: 'cors', 61 | }) 62 | .init() 63 | .then(() => 64 | // Test an endpoint if specified 65 | endpoint 66 | ? SupersetClient.request({ 67 | endpoint, 68 | method, 69 | postPayload: postPayload ? JSON.parse(postPayload) : '', 70 | }) 71 | : Promise.resolve({}), 72 | ) 73 | .then(response => this.setState({ didVerify: true, error: undefined, payload: response })) 74 | .catch((error: Response) => { 75 | const { status, statusText = error } = error; 76 | this.setState({ error: Error(`${status || ''}${status ? ':' : ''} ${statusText}`) }); 77 | }); 78 | } 79 | 80 | render() { 81 | const { didVerify, error, payload } = this.state; 82 | const { children } = this.props; 83 | 84 | return didVerify ? ( 85 | children({ payload }) 86 | ) : ( 87 |
88 |
89 | This example requires CORS requests from this domain.
90 |
91 | 1) enable CORS requests in your Superset App from{' '} 92 | {`${window.location.origin}`} 93 |
94 | 2) configure your Superset App host name below
95 | 3) click "Verify" to authenticate and fetch data for your test UI.
96 |
97 | 104 |
105 |
106 |
107 | 108 | {error && ( 109 |
110 | 111 |
112 | )} 113 |
114 | ); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /packages/superset-ui-plugins-demo/storybook/shared/components/createQueryStory.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { text, select } from '@storybook/addon-knobs'; 3 | import { SuperChart, ChartDataProvider } from '@superset-ui/chart'; 4 | import { SupersetClient } from '@superset-ui/connection'; 5 | import Expandable from './Expandable'; 6 | import VerifyCORS, { renderError } from './VerifyCORS'; 7 | 8 | export default function createQueryStory({ 9 | choices, 10 | storyName = 'Queries', 11 | storyPath = '', 12 | }: { 13 | choices: { 14 | [key: string]: { 15 | chartType: string; 16 | formData: { 17 | [key: string]: any; 18 | }; 19 | }; 20 | }; 21 | storyName: string; 22 | storyPath: string; 23 | }) { 24 | const keys = Object.keys(choices); 25 | 26 | return { 27 | renderStory: () => { 28 | const host = text('Set Superset App host for CORS request', 'localhost:8088'); 29 | const mode = select('Choose mode:', keys, keys[0]); 30 | const { formData: presetFormData, chartType } = choices[mode]; 31 | const width = text('Vis width', '400'); 32 | const height = text('Vis height', '400'); 33 | const formData = text('Override formData', JSON.stringify(presetFormData, null, 2)); 34 | 35 | return ( 36 |
37 | 38 | {() => ( 39 | 43 | {({ loading, payload, error }) => { 44 | if (loading) return
Loading!
; 45 | 46 | if (error) return renderError(error); 47 | 48 | if (payload) 49 | return ( 50 | <> 51 | 64 |
65 | 66 |
{JSON.stringify(payload, null, 2)}
67 |
68 | 69 | ); 70 | 71 | return null; 72 | }} 73 |
74 | )} 75 |
76 |
77 | ); 78 | }, 79 | storyName, 80 | storyPath, 81 | }; 82 | } 83 | -------------------------------------------------------------------------------- /packages/superset-ui-plugins-demo/storybook/shared/dummyDatasource.ts: -------------------------------------------------------------------------------- 1 | export default { verboseMap: {} }; 2 | -------------------------------------------------------------------------------- /packages/superset-ui-plugins-demo/storybook/stories/index.js: -------------------------------------------------------------------------------- 1 | import '@babel/polyfill'; 2 | import { setAddon, storiesOf } from '@storybook/react'; 3 | import { withKnobs } from '@storybook/addon-knobs'; 4 | import JSXAddon from 'storybook-addon-jsx'; 5 | import categoricalD3 from '@superset-ui/color/esm/colorSchemes/categorical/d3'; 6 | import sequentialCommon from '@superset-ui/color/esm/colorSchemes/sequential/common'; 7 | import sequentialD3 from '@superset-ui/color/esm/colorSchemes/sequential/d3'; 8 | import { configure } from '@superset-ui/translation'; 9 | import { getCategoricalSchemeRegistry, getSequentialSchemeRegistry } from '@superset-ui/color'; 10 | import { getTimeFormatterRegistry, smartDateFormatter } from '@superset-ui/time-format'; 11 | 12 | setAddon(JSXAddon); 13 | 14 | configure(); 15 | 16 | // Register color schemes 17 | const categoricalSchemeRegistry = getCategoricalSchemeRegistry(); 18 | [categoricalD3].forEach(group => { 19 | group.forEach(scheme => { 20 | categoricalSchemeRegistry.registerValue(scheme.id, scheme); 21 | }); 22 | }); 23 | categoricalSchemeRegistry.setDefaultKey('d3Category10'); 24 | 25 | const sequentialSchemeRegistry = getSequentialSchemeRegistry(); 26 | [sequentialCommon, sequentialD3].forEach(group => { 27 | group.forEach(scheme => { 28 | sequentialSchemeRegistry.registerValue(scheme.id, scheme); 29 | }); 30 | }); 31 | 32 | getTimeFormatterRegistry() 33 | .registerValue('smart_date', smartDateFormatter) 34 | .setDefaultKey('smart_date'); 35 | 36 | const EMPTY_EXAMPLES = [ 37 | { 38 | renderStory: () => 'Does your default export have an `examples` key?', 39 | storyName: 'No examples found', 40 | }, 41 | ]; 42 | 43 | /* 44 | * Below we crawl the dir + subdirs looking for index files of stories 45 | * Each index is expected to have a default export with examples key containing 46 | * an array of examples. Each example should have the shape: 47 | * { storyPath: string, storyName: string, renderStory: fn() => node } 48 | * 49 | */ 50 | const requireContext = require.context('./', /* subdirs= */ true, /index\.(js|ts)x?$/); 51 | 52 | requireContext.keys().forEach(packageName => { 53 | const packageExport = requireContext(packageName); 54 | if (packageExport && packageExport.default && !Array.isArray(packageExport.default)) { 55 | const { examples = EMPTY_EXAMPLES } = packageExport.default; 56 | 57 | examples.forEach(example => { 58 | const { 59 | storyPath = 'Missing story path', 60 | storyName = 'Missing name', 61 | renderStory = () => 'Missing `renderStory`', 62 | options = {}, 63 | } = example; 64 | 65 | storiesOf(storyPath, module) 66 | .addParameters({ options }) 67 | .addDecorator(withKnobs) 68 | .addWithJSX(storyName, renderStory); 69 | }); 70 | } 71 | }); 72 | -------------------------------------------------------------------------------- /packages/superset-ui-plugins-demo/storybook/stories/legacy-plugin-chart-event-flow/Stories.jsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-magic-numbers */ 2 | import React from 'react'; 3 | import { SuperChart } from '@superset-ui/chart'; 4 | import sampleEvents from '@data-ui/event-flow/build/sampleEvents'; 5 | 6 | const data = sampleEvents.twentyUsers.allEvents.map(({ ENTITY_ID, EVENT_NAME, TS }) => ({ 7 | __timestamp: TS, 8 | eventName: EVENT_NAME, 9 | userId: ENTITY_ID, 10 | })); 11 | 12 | export default [ 13 | { 14 | renderStory: () => ( 15 | 26 | ), 27 | storyName: 'Basic', 28 | storyPath: 'legacy-|plugin-chart-event-flow|EventFlowChartPlugin', 29 | }, 30 | ]; 31 | -------------------------------------------------------------------------------- /packages/superset-ui-plugins-demo/storybook/stories/legacy-plugin-chart-event-flow/index.js: -------------------------------------------------------------------------------- 1 | import EventFlowChartPlugin from '../../../../superset-ui-legacy-plugin-chart-event-flow'; 2 | import Stories from './Stories'; 3 | 4 | new EventFlowChartPlugin().configure({ key: 'event-flow' }).register(); 5 | 6 | export default { 7 | examples: [...Stories], 8 | }; 9 | -------------------------------------------------------------------------------- /packages/superset-ui-plugins-demo/storybook/stories/legacy-plugin-chart-word-cloud/Stories.tsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-magic-numbers */ 2 | import React from 'react'; 3 | import { SuperChart } from '@superset-ui/chart'; 4 | import data from './data'; 5 | 6 | export default [ 7 | { 8 | renderStory: () => ( 9 | 23 | ), 24 | storyName: 'Basic', 25 | storyPath: 'legacy-|plugin-chart-word-cloud|WordCloudChartPlugin', 26 | }, 27 | ]; 28 | -------------------------------------------------------------------------------- /packages/superset-ui-plugins-demo/storybook/stories/legacy-plugin-chart-word-cloud/data.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable sort-keys */ 2 | export default [ 3 | { 4 | name: 'Michael', 5 | sum__num: 2467129, 6 | }, 7 | { 8 | name: 'Christopher', 9 | sum__num: 1725328, 10 | }, 11 | { 12 | name: 'David', 13 | sum__num: 1570516, 14 | }, 15 | { 16 | name: 'James', 17 | sum__num: 1506095, 18 | }, 19 | { 20 | name: 'John', 21 | sum__num: 1426074, 22 | }, 23 | { 24 | name: 'Matthew', 25 | sum__num: 1355877, 26 | }, 27 | { 28 | name: 'Jennifer', 29 | sum__num: 1335587, 30 | }, 31 | { 32 | name: 'Robert', 33 | sum__num: 1314800, 34 | }, 35 | { 36 | name: 'Daniel', 37 | sum__num: 1159354, 38 | }, 39 | { 40 | name: 'Joseph', 41 | sum__num: 1114167, 42 | }, 43 | { 44 | name: 'William', 45 | sum__num: 1113793, 46 | }, 47 | { 48 | name: 'Joshua', 49 | sum__num: 1073440, 50 | }, 51 | { 52 | name: 'Jessica', 53 | sum__num: 997179, 54 | }, 55 | { 56 | name: 'Jason', 57 | sum__num: 955817, 58 | }, 59 | { 60 | name: 'Andrew', 61 | sum__num: 926315, 62 | }, 63 | { 64 | name: 'Anthony', 65 | sum__num: 878978, 66 | }, 67 | { 68 | name: 'Brian', 69 | sum__num: 874868, 70 | }, 71 | { 72 | name: 'Ryan', 73 | sum__num: 816288, 74 | }, 75 | { 76 | name: 'Kevin', 77 | sum__num: 791084, 78 | }, 79 | { 80 | name: 'Ashley', 81 | sum__num: 789363, 82 | }, 83 | { 84 | name: 'Thomas', 85 | sum__num: 746589, 86 | }, 87 | { 88 | name: 'Sarah', 89 | sum__num: 744956, 90 | }, 91 | { 92 | name: 'Nicholas', 93 | sum__num: 728617, 94 | }, 95 | { 96 | name: 'Amanda', 97 | sum__num: 719676, 98 | }, 99 | { 100 | name: 'Elizabeth', 101 | sum__num: 712676, 102 | }, 103 | { 104 | name: 'Justin', 105 | sum__num: 704646, 106 | }, 107 | { 108 | name: 'Jacob', 109 | sum__num: 700755, 110 | }, 111 | { 112 | name: 'Eric', 113 | sum__num: 700518, 114 | }, 115 | { 116 | name: 'Jonathan', 117 | sum__num: 691938, 118 | }, 119 | { 120 | name: 'Brandon', 121 | sum__num: 682546, 122 | }, 123 | { 124 | name: 'Melissa', 125 | sum__num: 664648, 126 | }, 127 | { 128 | name: 'Steven', 129 | sum__num: 659750, 130 | }, 131 | { 132 | name: 'Michelle', 133 | sum__num: 659302, 134 | }, 135 | { 136 | name: 'Richard', 137 | sum__num: 652854, 138 | }, 139 | { 140 | name: 'Kimberly', 141 | sum__num: 647609, 142 | }, 143 | { 144 | name: 'Timothy', 145 | sum__num: 632770, 146 | }, 147 | { 148 | name: 'Stephanie', 149 | sum__num: 628138, 150 | }, 151 | { 152 | name: 'Emily', 153 | sum__num: 614741, 154 | }, 155 | { 156 | name: 'Lisa', 157 | sum__num: 606540, 158 | }, 159 | { 160 | name: 'Mark', 161 | sum__num: 589103, 162 | }, 163 | { 164 | name: 'Jeffrey', 165 | sum__num: 557562, 166 | }, 167 | { 168 | name: 'Amy', 169 | sum__num: 556835, 170 | }, 171 | { 172 | name: 'Charles', 173 | sum__num: 556124, 174 | }, 175 | { 176 | name: 'Nicole', 177 | sum__num: 545099, 178 | }, 179 | { 180 | name: 'Tyler', 181 | sum__num: 499814, 182 | }, 183 | { 184 | name: 'Angela', 185 | sum__num: 496228, 186 | }, 187 | { 188 | name: 'Samantha', 189 | sum__num: 484266, 190 | }, 191 | { 192 | name: 'Benjamin', 193 | sum__num: 482709, 194 | }, 195 | { 196 | name: 'Heather', 197 | sum__num: 481474, 198 | }, 199 | { 200 | name: 'Scott', 201 | sum__num: 469933, 202 | }, 203 | { 204 | name: 'Rebecca', 205 | sum__num: 466847, 206 | }, 207 | { 208 | name: 'Adam', 209 | sum__num: 459794, 210 | }, 211 | { 212 | name: 'Mary', 213 | sum__num: 459471, 214 | }, 215 | { 216 | name: 'Zachary', 217 | sum__num: 459381, 218 | }, 219 | { 220 | name: 'Aaron', 221 | sum__num: 453035, 222 | }, 223 | { 224 | name: 'Rachel', 225 | sum__num: 444351, 226 | }, 227 | { 228 | name: 'Alexander', 229 | sum__num: 438239, 230 | }, 231 | { 232 | name: 'Paul', 233 | sum__num: 411513, 234 | }, 235 | { 236 | name: 'Kyle', 237 | sum__num: 409644, 238 | }, 239 | { 240 | name: 'Laura', 241 | sum__num: 408963, 242 | }, 243 | { 244 | name: 'Lauren', 245 | sum__num: 403946, 246 | }, 247 | { 248 | name: 'Megan', 249 | sum__num: 402100, 250 | }, 251 | { 252 | name: 'Nathan', 253 | sum__num: 393793, 254 | }, 255 | { 256 | name: 'Samuel', 257 | sum__num: 390363, 258 | }, 259 | { 260 | name: 'Christina', 261 | sum__num: 387580, 262 | }, 263 | { 264 | name: 'Kelly', 265 | sum__num: 384611, 266 | }, 267 | { 268 | name: 'Jordan', 269 | sum__num: 382963, 270 | }, 271 | { 272 | name: 'Patrick', 273 | sum__num: 382673, 274 | }, 275 | { 276 | name: 'Jeremy', 277 | sum__num: 381171, 278 | }, 279 | { 280 | name: 'Jose', 281 | sum__num: 377759, 282 | }, 283 | { 284 | name: 'Stephen', 285 | sum__num: 374269, 286 | }, 287 | { 288 | name: 'Sean', 289 | sum__num: 366228, 290 | }, 291 | { 292 | name: 'Kenneth', 293 | sum__num: 361043, 294 | }, 295 | { 296 | name: 'Gregory', 297 | sum__num: 334166, 298 | }, 299 | { 300 | name: 'Brittany', 301 | sum__num: 333252, 302 | }, 303 | { 304 | name: 'Amber', 305 | sum__num: 331563, 306 | }, 307 | { 308 | name: 'Katherine', 309 | sum__num: 329873, 310 | }, 311 | { 312 | name: 'Hannah', 313 | sum__num: 329227, 314 | }, 315 | { 316 | name: 'Taylor', 317 | sum__num: 327602, 318 | }, 319 | { 320 | name: 'Danielle', 321 | sum__num: 322578, 322 | }, 323 | { 324 | name: 'Andrea', 325 | sum__num: 318796, 326 | }, 327 | { 328 | name: 'Austin', 329 | sum__num: 314059, 330 | }, 331 | { 332 | name: 'Tiffany', 333 | sum__num: 301753, 334 | }, 335 | { 336 | name: 'Kayla', 337 | sum__num: 291858, 338 | }, 339 | { 340 | name: 'Christian', 341 | sum__num: 288189, 342 | }, 343 | { 344 | name: 'Maria', 345 | sum__num: 287870, 346 | }, 347 | { 348 | name: 'Alexis', 349 | sum__num: 286496, 350 | }, 351 | { 352 | name: 'Bryan', 353 | sum__num: 282841, 354 | }, 355 | { 356 | name: 'Victoria', 357 | sum__num: 277371, 358 | }, 359 | { 360 | name: 'Julie', 361 | sum__num: 270542, 362 | }, 363 | { 364 | name: 'Shannon', 365 | sum__num: 266886, 366 | }, 367 | { 368 | name: 'Christine', 369 | sum__num: 264122, 370 | }, 371 | { 372 | name: 'Sara', 373 | sum__num: 263050, 374 | }, 375 | { 376 | name: 'Erin', 377 | sum__num: 262817, 378 | }, 379 | { 380 | name: 'Madison', 381 | sum__num: 262812, 382 | }, 383 | { 384 | name: 'Crystal', 385 | sum__num: 262697, 386 | }, 387 | { 388 | name: 'Karen', 389 | sum__num: 257961, 390 | }, 391 | { 392 | name: 'Anna', 393 | sum__num: 256136, 394 | }, 395 | { 396 | name: 'Dylan', 397 | sum__num: 250778, 398 | }, 399 | { 400 | name: 'Edward', 401 | sum__num: 248689, 402 | }, 403 | ]; 404 | -------------------------------------------------------------------------------- /packages/superset-ui-plugins-demo/storybook/stories/legacy-plugin-chart-word-cloud/index.js: -------------------------------------------------------------------------------- 1 | import WordCloudChartPlugin from '../../../../superset-ui-legacy-plugin-chart-word-cloud'; 2 | import Stories from './Stories'; 3 | 4 | new WordCloudChartPlugin().configure({ key: 'word-cloud' }).register(); 5 | 6 | export default { 7 | examples: [...Stories], 8 | }; 9 | -------------------------------------------------------------------------------- /packages/superset-ui-plugins-demo/storybook/stories/plugin-chart-table/Stories.jsx: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-magic-numbers */ 2 | import React from 'react'; 3 | import { SuperChart } from '@superset-ui/chart'; 4 | import dataLegacy from './dataLegacy'; 5 | import data from './data'; 6 | import generateData from './generateData'; 7 | 8 | const dataset30Rows = { data: generateData(30) }; 9 | const dataset1000Rows = { data: generateData(1000) }; 10 | 11 | export default [ 12 | { 13 | renderStory: () => ( 14 | 38 | ), 39 | storyName: 'Legacy', 40 | storyPath: 'plugin-chart-table|TableChartPlugin', 41 | }, 42 | { 43 | renderStory: () => ( 44 | 68 | ), 69 | storyName: 'Legacy-TableFilter', 70 | storyPath: 'plugin-chart-table|TableChartPlugin', 71 | }, 72 | { 73 | renderStory: () => ( 74 | 98 | ), 99 | storyName: 'TableFilter', 100 | storyPath: 'plugin-chart-table|TableChartPlugin', 101 | }, 102 | { 103 | renderStory: () => ( 104 | 127 | ), 128 | storyName: '30 rows 20 columns', 129 | storyPath: 'plugin-chart-table|TableChartPlugin', 130 | }, 131 | { 132 | renderStory: () => ( 133 | 154 | ), 155 | storyName: '1000 rows 20 columns', 156 | storyPath: 'plugin-chart-table|TableChartPlugin', 157 | }, 158 | ]; 159 | -------------------------------------------------------------------------------- /packages/superset-ui-plugins-demo/storybook/stories/plugin-chart-table/data.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable sort-keys */ 2 | export default [ 3 | { 4 | name: 'Michael', 5 | sum__num: 2467063, 6 | }, 7 | { 8 | name: 'Christopher', 9 | sum__num: 1725265, 10 | }, 11 | { 12 | name: 'David', 13 | sum__num: 1570516, 14 | }, 15 | { 16 | name: 'James', 17 | sum__num: 1506025, 18 | }, 19 | { 20 | name: 'john', 21 | sum__num: 1426074, 22 | }, 23 | { 24 | name: 'Matthew', 25 | sum__num: 1355803, 26 | }, 27 | { 28 | name: 'Robert', 29 | sum__num: 1314800, 30 | }, 31 | { 32 | name: 'Daniel', 33 | sum__num: 1159354, 34 | }, 35 | { 36 | name: 'Joseph', 37 | sum__num: 1114098, 38 | }, 39 | { 40 | name: 'William', 41 | sum__num: 1113701, 42 | }, 43 | ]; 44 | -------------------------------------------------------------------------------- /packages/superset-ui-plugins-demo/storybook/stories/plugin-chart-table/dataLegacy.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable sort-keys */ 2 | export default { 3 | columns: ['name', 'sum__num', '%sum__num', 'trend', 'is_girl'], 4 | records: [ 5 | { 6 | name: 'Michael', 7 | sum__num: 2467063, 8 | '%sum__num': 0.2, 9 | trend: 0, 10 | is_girl: false, 11 | }, 12 | { 13 | name: 'Christopher', 14 | sum__num: 1725265, 15 | '%sum__num': 0.2, 16 | trend: 17, 17 | is_girl: true, 18 | }, 19 | { 20 | name: 'David', 21 | sum__num: 1570516, 22 | '%sum__num': 0.15, 23 | trend: 21, 24 | is_girl: true, 25 | }, 26 | { 27 | name: 'James', 28 | sum__num: 1506025, 29 | '%sum__num': 0.14, 30 | trend: 1, 31 | is_girl: true, 32 | }, 33 | { 34 | name: 'john', 35 | sum__num: 1426074, 36 | '%sum__num': 0.12, 37 | trend: -2, 38 | is_girl: true, 39 | }, 40 | { 41 | name: 'Matthew', 42 | sum__num: 1355803, 43 | '%sum__num': 0.1, 44 | trend: -10, 45 | is_girl: true, 46 | }, 47 | { 48 | name: 'Robert', 49 | sum__num: 1314800, 50 | '%sum__num': 0.03, 51 | trend: 24, 52 | is_girl: true, 53 | }, 54 | { 55 | name: 'Daniel', 56 | sum__num: 1159354, 57 | '%sum__num': 0.02, 58 | trend: 25, 59 | is_girl: true, 60 | }, 61 | { 62 | name: 'Joseph', 63 | sum__num: 1114098, 64 | '%sum__num': 0.02, 65 | trend: 10, 66 | is_girl: false, 67 | }, 68 | { 69 | name: 'William', 70 | sum__num: 1113701, 71 | '%sum__num': 0.02, 72 | trend: 10, 73 | is_girl: null, 74 | }, 75 | ], 76 | }; 77 | -------------------------------------------------------------------------------- /packages/superset-ui-plugins-demo/storybook/stories/plugin-chart-table/generateData.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-unused-vars */ 2 | /* eslint-disable no-magic-numbers */ 3 | /* eslint-disable sort-keys */ 4 | 5 | const getHTML = () => { 6 | const randomText = Array(Math.floor(Math.random() * 50)) 7 | .fill('very') 8 | .join('_'); 9 | 10 | return `Link Test with a ${randomText} long title`; 11 | }; 12 | 13 | export default function generateData(rowCount = 30, columnCount = 20) { 14 | const columns = Array(columnCount) 15 | .fill(0) 16 | .map((_, i) => `clm${i}`); 17 | 18 | return Array(rowCount) 19 | .fill(0) 20 | .map((_, index) => ({ 21 | index: index + 1, 22 | html: getHTML(), 23 | ...columns.reduce( 24 | (prev, key, i) => { 25 | const obj = prev; 26 | // eslint-disable-next-line no-restricted-properties 27 | obj[key] = Math.round(Math.random() * Math.pow(10, columnCount - i)); 28 | 29 | return obj; 30 | }, 31 | { 32 | ds: '2019-09-09', 33 | }, 34 | ), 35 | })); 36 | } 37 | -------------------------------------------------------------------------------- /packages/superset-ui-plugins-demo/storybook/stories/plugin-chart-table/index.js: -------------------------------------------------------------------------------- 1 | import TableChartPlugin from '../../../../superset-ui-plugin-chart-table/src'; 2 | import TableChartPluginLegacy from '../../../../superset-ui-plugin-chart-table/src/legacy'; 3 | import Stories from './Stories'; 4 | 5 | new TableChartPlugin().configure({ key: 'table2' }).register(); 6 | new TableChartPluginLegacy().configure({ key: 'table2-legacy' }).register(); 7 | 8 | export default { 9 | examples: [...Stories], 10 | }; 11 | -------------------------------------------------------------------------------- /packages/superset-ui-plugins-demo/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowJs": true, 4 | "allowSyntheticDefaultImports": true, 5 | "baseUrl": ".", 6 | "outDir": "./dist", 7 | "esModuleInterop": true, 8 | "forceConsistentCasingInFileNames": true, 9 | "importHelpers": true, 10 | "jsx": "react", 11 | "lib": ["dom", "esnext"], 12 | "module": "commonjs", 13 | "moduleResolution": "node", 14 | "noEmitOnError": true, 15 | "noImplicitReturns": true, 16 | "noImplicitThis": true, 17 | "noImplicitAny": true, 18 | "noUnusedLocals": true, 19 | "pretty": true, 20 | "removeComments": false, 21 | "resolveJsonModule": true, 22 | "strictNullChecks": true, 23 | "suppressImplicitAnyIndexErrors": true, 24 | "skipLibCheck": true, 25 | "sourceMap": true, 26 | "target": "esnext" 27 | }, 28 | "include": ["./storybook/stories/**/*", "../superset-ui-*/src/**/*", "./src/**/*", "./spec/**/*", "storybook/shared/dummyDatasource.ts"] 29 | } 30 | -------------------------------------------------------------------------------- /scripts/build.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Build only plugins specified by globs 3 | */ 4 | const { spawnSync } = require('child_process'); 5 | 6 | const glob = process.argv[2]; 7 | const extraArgs = process.argv.slice(2); 8 | 9 | process.env.PATH = `./node_modules/.bin:${process.env.PATH}`; 10 | 11 | const run = cmd => { 12 | console.log(`>> ${cmd}`); 13 | const [p, ...args] = cmd.split(' '); 14 | const runner = spawnSync; 15 | const { status } = runner(p, args, { stdio: 'inherit' }); 16 | if (status !== 0) { 17 | process.exit(status); 18 | } 19 | }; 20 | 21 | if (glob) { 22 | run(`nimbus prettier packages/${glob}/{src,test}/**/*.{js,jsx,ts,tsx,css}"`); 23 | // lint is slow, so not turning it on by default 24 | if (extraArgs.includes('--lint')) { 25 | run(`nimbus eslint packages/${glob}/{src,test}`); 26 | } 27 | run(`nimbus babel --clean --workspaces="@superset-ui/${glob}"`); 28 | run(`nimbus babel --clean --workspaces="@superset-ui/${glob}" --esm`); 29 | run(`nimbus typescript --build --workspaces="@superset-ui/${glob}"`); 30 | require('./buildAssets'); 31 | } else { 32 | run('yarn build'); 33 | } 34 | -------------------------------------------------------------------------------- /scripts/buildAssets.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable import/no-extraneous-dependencies, no-console */ 2 | const fg = require('fast-glob'); 3 | const fs = require('fs-extra'); 4 | 5 | const packages = fg.sync([`packages/${process.argv[2] || '*'}`], { 6 | onlyDirectories: true, 7 | }); 8 | 9 | console.log('Copying asset files from `src` to {lib,esm}...'); 10 | packages.forEach(pkg => { 11 | const assets = fg.sync([`${pkg}/src/**/*.{png,gif,jpg,css,geojson}`]); 12 | assets.forEach(filePath => { 13 | const newPaths = ['lib', 'esm'].map(dir => filePath.replace(`${pkg}/src`, `${pkg}/${dir}`)); 14 | newPaths.forEach(p => { 15 | fs.copy(filePath, p, err => { 16 | if (err) { 17 | console.error(err); 18 | } 19 | }); 20 | }); 21 | }); 22 | console.log( 23 | ` Copied ${assets.length.toString().padStart(2)} asset files for ${pkg.replace( 24 | 'packages/superset-ui-', 25 | '', 26 | )}`, 27 | ); 28 | }); 29 | -------------------------------------------------------------------------------- /scripts/setupJest.js: -------------------------------------------------------------------------------- 1 | import { configure as configureTranslation } from '@superset-ui/translation'; 2 | import { configure as configureEnzyme } from 'enzyme'; 3 | import EnzymeReactAdapter from 'enzyme-adapter-react-16'; 4 | 5 | configureTranslation(); 6 | configureEnzyme({ adapter: new EnzymeReactAdapter() }); 7 | --------------------------------------------------------------------------------