mirror of https://github.com/apache/superset.git
Merge pull request #17445 from zhaoyongjie/monorepo_relocate_superset_ui
refactor(monorepo): relocate superset-ui
This commit is contained in:
commit
870d2ab16f
|
@ -14,7 +14,6 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
*.ipynb
|
|
||||||
*.bak
|
*.bak
|
||||||
*.db
|
*.db
|
||||||
*.pyc
|
*.pyc
|
||||||
|
|
|
@ -49,4 +49,5 @@ repos:
|
||||||
rev: v2.4.1 # Use the sha or tag you want to point at
|
rev: v2.4.1 # Use the sha or tag you want to point at
|
||||||
hooks:
|
hooks:
|
||||||
- id: prettier
|
- id: prettier
|
||||||
|
args: ['--ignore-path=./superset-frontend/.prettierignore']
|
||||||
files: 'superset-frontend'
|
files: 'superset-frontend'
|
||||||
|
|
|
@ -59,5 +59,5 @@ tsconfig.tsbuildinfo
|
||||||
.*iml
|
.*iml
|
||||||
.esprintrc
|
.esprintrc
|
||||||
.prettierignore
|
.prettierignore
|
||||||
superset-frontend/packages/generator-superset
|
generator-superset/*
|
||||||
superset-frontend/temporary_superset_ui
|
temporary_superset_ui/*
|
||||||
|
|
|
@ -28,3 +28,4 @@ src/dashboard/deprecated/*
|
||||||
src/temp/*
|
src/temp/*
|
||||||
**/node_modules
|
**/node_modules
|
||||||
*.d.ts
|
*.d.ts
|
||||||
|
temporary_superset_ui/**/*
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
#
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
# contributor license agreements. See the NOTICE file distributed with
|
||||||
|
# this work for additional information regarding copyright ownership.
|
||||||
|
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||||
|
# (the "License"); you may not use this file except in compliance with
|
||||||
|
# the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
coverage/
|
||||||
|
esm/
|
||||||
|
lib/
|
||||||
|
tmp/
|
||||||
|
node_modules/
|
||||||
|
tsconfig.json
|
||||||
|
CHANGELOG.md
|
||||||
|
*.geojson
|
||||||
|
*-topo.json
|
||||||
|
temporary_superset_ui/
|
|
@ -26,6 +26,7 @@ module.exports = {
|
||||||
'^spec/(.*)$': '<rootDir>/spec/$1',
|
'^spec/(.*)$': '<rootDir>/spec/$1',
|
||||||
},
|
},
|
||||||
testEnvironment: 'jsdom',
|
testEnvironment: 'jsdom',
|
||||||
|
modulePathIgnorePatterns: ['<rootDir>/temporary_superset_ui'],
|
||||||
setupFilesAfterEnv: ['<rootDir>/spec/helpers/setup.ts'],
|
setupFilesAfterEnv: ['<rootDir>/spec/helpers/setup.ts'],
|
||||||
testURL: 'http://localhost',
|
testURL: 'http://localhost',
|
||||||
collectCoverageFrom: ['src/**/*.{js,jsx,ts,tsx}', '!**/*.stories.*'],
|
collectCoverageFrom: ['src/**/*.{js,jsx,ts,tsx}', '!**/*.stories.*'],
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
"lerna": "3.2.1",
|
||||||
|
"npmClient": "npm",
|
||||||
|
"packages": ["packages/*", "plugins/*", "temporary_superset_ui/*"],
|
||||||
|
"useWorkspaces": true,
|
||||||
|
"version": "0.0.0",
|
||||||
|
"ignoreChanges": [
|
||||||
|
"**/*.md",
|
||||||
|
"**/*.spec.tsx?",
|
||||||
|
"**/*.spec.jsx?",
|
||||||
|
"**/__mocks__/**"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
coverage/
|
||||||
|
node_modules/
|
||||||
|
public/
|
||||||
|
esm/
|
||||||
|
lib/
|
||||||
|
tmp/
|
||||||
|
dist/
|
||||||
|
temporary-plugins/
|
||||||
|
storybook-static/
|
|
@ -0,0 +1,297 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
module.exports = {
|
||||||
|
extends: [
|
||||||
|
'airbnb',
|
||||||
|
'prettier',
|
||||||
|
'prettier/react',
|
||||||
|
'plugin:react-hooks/recommended',
|
||||||
|
],
|
||||||
|
parser: '@babel/eslint-parser',
|
||||||
|
parserOptions: {
|
||||||
|
ecmaFeatures: {
|
||||||
|
experimentalObjectRestSpread: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
env: {
|
||||||
|
browser: true,
|
||||||
|
},
|
||||||
|
settings: {
|
||||||
|
'import/resolver': {
|
||||||
|
webpack: {},
|
||||||
|
node: {
|
||||||
|
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Allow core/src and core/test, not import modules from lib
|
||||||
|
'import/internal-regex': /^@superset-ui\/core\/(src|test)/,
|
||||||
|
'import/core-modules': [
|
||||||
|
'@superset-ui/core',
|
||||||
|
'@superset-ui/chart-controls',
|
||||||
|
'@superset-ui/legacy-plugin-chart-calendar',
|
||||||
|
'@superset-ui/legacy-plugin-chart-chord',
|
||||||
|
'@superset-ui/legacy-plugin-chart-country-map',
|
||||||
|
'@superset-ui/legacy-plugin-chart-event-flow',
|
||||||
|
'@superset-ui/legacy-plugin-chart-force-directed',
|
||||||
|
'@superset-ui/legacy-plugin-chart-heatmap',
|
||||||
|
'@superset-ui/legacy-plugin-chart-histogram',
|
||||||
|
'@superset-ui/legacy-plugin-chart-horizon',
|
||||||
|
'@superset-ui/legacy-plugin-chart-map-box',
|
||||||
|
'@superset-ui/legacy-plugin-chart-paired-t-test',
|
||||||
|
'@superset-ui/legacy-plugin-chart-parallel-coordinates',
|
||||||
|
'@superset-ui/legacy-plugin-chart-partition',
|
||||||
|
'@superset-ui/legacy-plugin-chart-pivot-table',
|
||||||
|
'@superset-ui/legacy-plugin-chart-rose',
|
||||||
|
'@superset-ui/legacy-plugin-chart-sankey',
|
||||||
|
'@superset-ui/legacy-plugin-chart-sankey-loop',
|
||||||
|
'@superset-ui/legacy-plugin-chart-sunburst',
|
||||||
|
'@superset-ui/legacy-plugin-chart-time-table',
|
||||||
|
'@superset-ui/legacy-plugin-chart-treemap',
|
||||||
|
'@superset-ui/legacy-plugin-chart-world-map',
|
||||||
|
'@superset-ui/legacy-preset-chart-big-number',
|
||||||
|
'@superset-ui/legacy-preset-chart-nvd3',
|
||||||
|
'@superset-ui/plugin-chart-echarts',
|
||||||
|
'@superset-ui/plugin-chart-table',
|
||||||
|
'@superset-ui/plugin-chart-word-cloud',
|
||||||
|
'@superset-ui/preset-chart-xy',
|
||||||
|
],
|
||||||
|
react: {
|
||||||
|
version: 'detect',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: ['prettier', 'react'],
|
||||||
|
rules: {
|
||||||
|
camelcase: [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
allow: ['^UNSAFE_'],
|
||||||
|
properties: 'never',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
curly: 2,
|
||||||
|
'class-methods-use-this': 0,
|
||||||
|
'func-names': 0,
|
||||||
|
'guard-for-in': 0,
|
||||||
|
'import/extensions': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
'.js': 'always',
|
||||||
|
'.jsx': 'always',
|
||||||
|
'.ts': 'always',
|
||||||
|
'.tsx': 'always',
|
||||||
|
'.json': 'always',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'import/no-cycle': 0, // re-enable up for discussion, might require some major refactors
|
||||||
|
'import/prefer-default-export': 0,
|
||||||
|
indent: 0,
|
||||||
|
'jsx-a11y/anchor-is-valid': 0, // disabled temporarily
|
||||||
|
'jsx-a11y/click-events-have-key-events': 0, // re-enable up for discussion
|
||||||
|
'jsx-a11y/mouse-events-have-key-events': 0, // re-enable up for discussion
|
||||||
|
'new-cap': 0,
|
||||||
|
'no-bitwise': 0,
|
||||||
|
'no-continue': 0,
|
||||||
|
'no-mixed-operators': 0,
|
||||||
|
'no-multi-assign': 0,
|
||||||
|
'no-multi-spaces': 0,
|
||||||
|
'no-nested-ternary': 0,
|
||||||
|
'no-prototype-builtins': 0,
|
||||||
|
'no-restricted-properties': 0,
|
||||||
|
'no-restricted-imports': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
paths: [
|
||||||
|
{
|
||||||
|
name: 'antd',
|
||||||
|
message:
|
||||||
|
'Please import Ant components from the index of common/components',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'no-shadow': 0, // re-enable up for discussion
|
||||||
|
'padded-blocks': 0,
|
||||||
|
'prefer-arrow-callback': 0,
|
||||||
|
'prefer-object-spread': 1,
|
||||||
|
'prefer-destructuring': ['error', { object: true, array: false }],
|
||||||
|
'react/destructuring-assignment': 0, // re-enable up for discussion
|
||||||
|
'react/forbid-prop-types': 0,
|
||||||
|
'react/jsx-filename-extension': [1, { extensions: ['.jsx', '.tsx'] }],
|
||||||
|
'react/jsx-fragments': 1,
|
||||||
|
'react/jsx-no-bind': 0,
|
||||||
|
'react/jsx-props-no-spreading': 0, // re-enable up for discussion
|
||||||
|
'react/no-array-index-key': 0,
|
||||||
|
'react/no-string-refs': 0,
|
||||||
|
'react/no-unescaped-entities': 0,
|
||||||
|
'react/no-unused-prop-types': 0,
|
||||||
|
'react/prop-types': 0,
|
||||||
|
'react/require-default-props': 0,
|
||||||
|
'react/static-property-placement': 0, // disabled temporarily
|
||||||
|
'prettier/prettier': 'error',
|
||||||
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: ['*.ts', '*.tsx'],
|
||||||
|
parser: '@typescript-eslint/parser',
|
||||||
|
extends: [
|
||||||
|
'airbnb',
|
||||||
|
'plugin:@typescript-eslint/recommended',
|
||||||
|
'prettier',
|
||||||
|
'prettier/@typescript-eslint',
|
||||||
|
'prettier/react',
|
||||||
|
],
|
||||||
|
plugins: ['@typescript-eslint/eslint-plugin', 'prettier', 'react'],
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/ban-ts-ignore': 0,
|
||||||
|
'@typescript-eslint/ban-ts-comment': 0, // disabled temporarily
|
||||||
|
'@typescript-eslint/ban-types': 0, // disabled temporarily
|
||||||
|
'@typescript-eslint/no-empty-function': 0,
|
||||||
|
'@typescript-eslint/no-explicit-any': 0,
|
||||||
|
'@typescript-eslint/no-use-before-define': 1,
|
||||||
|
'@typescript-eslint/no-non-null-assertion': 0, // disabled temporarily
|
||||||
|
'@typescript-eslint/explicit-function-return-type': 0,
|
||||||
|
'@typescript-eslint/explicit-module-boundary-types': 0, // re-enable up for discussion
|
||||||
|
camelcase: 0,
|
||||||
|
'class-methods-use-this': 0,
|
||||||
|
'func-names': 0,
|
||||||
|
'guard-for-in': 0,
|
||||||
|
// there is a bug related to re-exports with this rule
|
||||||
|
// which doesn't seem to have been fixed: https://github.com/benmosher/eslint-plugin-import/issues/1460
|
||||||
|
'import/named': 0,
|
||||||
|
'import/no-cycle': 0, // re-enable up for discussion, might require some major refactors
|
||||||
|
'import/extensions': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
'.ts': 'always',
|
||||||
|
'.tsx': 'always',
|
||||||
|
'.json': 'always',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'import/no-named-as-default-member': 0,
|
||||||
|
'import/prefer-default-export': 0,
|
||||||
|
indent: 0,
|
||||||
|
'jsx-a11y/anchor-is-valid': 0, // disabled temporarily
|
||||||
|
'jsx-a11y/click-events-have-key-events': 0, // re-enable up for discussion
|
||||||
|
'jsx-a11y/mouse-events-have-key-events': 0, // re-enable up for discussion
|
||||||
|
'new-cap': 0,
|
||||||
|
'no-bitwise': 0,
|
||||||
|
'no-continue': 0,
|
||||||
|
'no-mixed-operators': 0,
|
||||||
|
'no-multi-assign': 0,
|
||||||
|
'no-multi-spaces': 0,
|
||||||
|
'no-nested-ternary': 0,
|
||||||
|
'no-prototype-builtins': 0,
|
||||||
|
'no-restricted-properties': 0,
|
||||||
|
'no-shadow': 0, // re-enable up for discussion
|
||||||
|
'no-use-before-define': 0, // disabled temporarily
|
||||||
|
'padded-blocks': 0,
|
||||||
|
'prefer-arrow-callback': 0,
|
||||||
|
'prefer-destructuring': ['error', { object: true, array: false }],
|
||||||
|
'react/destructuring-assignment': 0, // re-enable up for discussion
|
||||||
|
'react/forbid-prop-types': 0,
|
||||||
|
'react/jsx-filename-extension': [1, { extensions: ['.jsx', '.tsx'] }],
|
||||||
|
'react/jsx-fragments': 1,
|
||||||
|
'react/jsx-no-bind': 0,
|
||||||
|
'react/jsx-props-no-spreading': 0, // re-enable up for discussion
|
||||||
|
'react/no-array-index-key': 0,
|
||||||
|
'react/no-string-refs': 0,
|
||||||
|
'react/no-unescaped-entities': 0,
|
||||||
|
'react/no-unused-prop-types': 0,
|
||||||
|
'react/prop-types': 0,
|
||||||
|
'react/require-default-props': 0,
|
||||||
|
'react/static-property-placement': 0, // re-enable up for discussion
|
||||||
|
'react/sort-comp': 0,
|
||||||
|
'prettier/prettier': 'error',
|
||||||
|
},
|
||||||
|
settings: {
|
||||||
|
'import/resolver': {
|
||||||
|
webpack: {},
|
||||||
|
typescript: {},
|
||||||
|
},
|
||||||
|
react: {
|
||||||
|
version: 'detect',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['*.stories.jsx', '*.stories.tsx'],
|
||||||
|
rules: {
|
||||||
|
// this is to keep eslint from complaining about storybook addons,
|
||||||
|
// since they are included as dev dependencies rather than direct dependencies.
|
||||||
|
'import/no-extraneous-dependencies': [
|
||||||
|
'error',
|
||||||
|
{ devDependencies: true },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['*.d.ts'],
|
||||||
|
rules: {
|
||||||
|
'max-classes-per-file': 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: [
|
||||||
|
'*.test.ts',
|
||||||
|
'*.test.tsx',
|
||||||
|
'*.test.js',
|
||||||
|
'*.test.jsx',
|
||||||
|
'fixtures.*',
|
||||||
|
],
|
||||||
|
plugins: ['jest', 'jest-dom', 'no-only-tests', 'testing-library'],
|
||||||
|
env: {
|
||||||
|
'jest/globals': true,
|
||||||
|
},
|
||||||
|
extends: ['plugin:jest/recommended', 'plugin:testing-library/react'],
|
||||||
|
rules: {
|
||||||
|
'import/no-extraneous-dependencies': 0,
|
||||||
|
'jest/consistent-test-it': 'error',
|
||||||
|
'jest/no-try-expect': 0,
|
||||||
|
'max-classes-per-file': 0,
|
||||||
|
'no-only-tests/no-only-tests': 'error',
|
||||||
|
'prefer-promise-reject-errors': 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['webpack*.js', '.*rc.js', '*.config.js'],
|
||||||
|
env: {
|
||||||
|
node: true,
|
||||||
|
},
|
||||||
|
settings: {
|
||||||
|
'import/resolver': {
|
||||||
|
node: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: './packages/generator-superset/**/*.test.*',
|
||||||
|
env: {
|
||||||
|
node: true,
|
||||||
|
},
|
||||||
|
settings: {
|
||||||
|
'import/resolver': {
|
||||||
|
node: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'jest/expect-expect': 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
|
@ -0,0 +1,12 @@
|
||||||
|
# See https://help.github.com/articles/about-codeowners/
|
||||||
|
# for more info about CODEOWNERS file
|
||||||
|
|
||||||
|
# It uses the same pattern rule for gitignore file
|
||||||
|
# https://git-scm.com/docs/gitignore#_pattern_format
|
||||||
|
|
||||||
|
# These owners will be the default owners for everything in
|
||||||
|
# the repo. Unless a later match takes precedence,
|
||||||
|
# these users/team will be requested for review
|
||||||
|
# when someone opens a pull request.
|
||||||
|
|
||||||
|
* @apache-superset/embeddable-charts-team
|
35
superset-frontend/temporary_superset_ui/superset-ui/.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
35
superset-frontend/temporary_superset_ui/superset-ui/.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
---
|
||||||
|
|
||||||
|
### Describe the bug
|
||||||
|
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
### To Reproduce
|
||||||
|
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
### Expected behavior
|
||||||
|
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
### Screenshots
|
||||||
|
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
### Environment (please complete the following information):
|
||||||
|
|
||||||
|
- superset-ui version: [e.g. v0.5.0]
|
||||||
|
- Node version: `node -v`
|
||||||
|
- npm version: `npm -v`
|
||||||
|
|
||||||
|
### Additional context
|
||||||
|
|
||||||
|
Add any other context about the problem here.
|
18
superset-frontend/temporary_superset_ui/superset-ui/.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
18
superset-frontend/temporary_superset_ui/superset-ui/.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
---
|
||||||
|
|
||||||
|
### Is your feature request related to a problem? Please describe.
|
||||||
|
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
### Describe the solution you'd like
|
||||||
|
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
### Describe alternatives you've considered
|
||||||
|
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
### Additional context\*\* Add any other context or screenshots about the feature request here.
|
8
superset-frontend/temporary_superset_ui/superset-ui/.github/ISSUE_TEMPLATE/question.md
vendored
Normal file
8
superset-frontend/temporary_superset_ui/superset-ui/.github/ISSUE_TEMPLATE/question.md
vendored
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
name: Question
|
||||||
|
about: Ask for help with something.
|
||||||
|
---
|
||||||
|
|
||||||
|
Your question.
|
||||||
|
|
||||||
|
- How do I xxx?
|
9
superset-frontend/temporary_superset_ui/superset-ui/.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
9
superset-frontend/temporary_superset_ui/superset-ui/.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
💔 Breaking Changes
|
||||||
|
|
||||||
|
🏆 Enhancements
|
||||||
|
|
||||||
|
📜 Documentation
|
||||||
|
|
||||||
|
🐛 Bug Fix
|
||||||
|
|
||||||
|
🏠 Internal
|
|
@ -0,0 +1,14 @@
|
||||||
|
# Configuration for request-info - https://github.com/behaviorbot/request-info
|
||||||
|
|
||||||
|
# *Required* Comment to reply with
|
||||||
|
requestInfoReplyComment: >
|
||||||
|
We would appreciate it if you could provide us with more info about this issue/pr!
|
||||||
|
|
||||||
|
# *OPTIONAL* default titles to check against for lack of descriptiveness
|
||||||
|
# MUST BE ALL LOWERCASE
|
||||||
|
requestInfoDefaultTitles:
|
||||||
|
- update readme.md
|
||||||
|
- updates
|
||||||
|
|
||||||
|
# *OPTIONAL* Label to be added to Issues and Pull Requests with insufficient information given
|
||||||
|
requestInfoLabelToAdd: needs-more-info
|
|
@ -0,0 +1,53 @@
|
||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: npm
|
||||||
|
directory: '/'
|
||||||
|
schedule:
|
||||||
|
interval: daily
|
||||||
|
open-pull-requests-limit: 10
|
||||||
|
ignore:
|
||||||
|
- dependency-name: bootstrap
|
||||||
|
versions:
|
||||||
|
- '>= 4.a, < 5'
|
||||||
|
- dependency-name: d3
|
||||||
|
versions:
|
||||||
|
- '>= 6.a, < 7'
|
||||||
|
- dependency-name: '@types/jsdom'
|
||||||
|
versions:
|
||||||
|
- '> 12.2.4'
|
||||||
|
- dependency-name: '@types/react'
|
||||||
|
versions:
|
||||||
|
- 17.0.1
|
||||||
|
- 17.0.2
|
||||||
|
- 17.0.3
|
||||||
|
- dependency-name: '@babel/preset-env'
|
||||||
|
versions:
|
||||||
|
- 7.12.13
|
||||||
|
- 7.13.10
|
||||||
|
- 7.13.12
|
||||||
|
- 7.13.9
|
||||||
|
- dependency-name: '@babel/compat-data'
|
||||||
|
versions:
|
||||||
|
- 7.12.13
|
||||||
|
- 7.13.0
|
||||||
|
- 7.13.11
|
||||||
|
- 7.13.12
|
||||||
|
- 7.13.6
|
||||||
|
- 7.13.8
|
||||||
|
- dependency-name: elliptic
|
||||||
|
versions:
|
||||||
|
- 6.5.3
|
||||||
|
- 6.5.4
|
||||||
|
- dependency-name: yeoman-test
|
||||||
|
versions:
|
||||||
|
- 4.0.0
|
||||||
|
- 5.0.1
|
||||||
|
- dependency-name: '@emotion/core'
|
||||||
|
versions:
|
||||||
|
- 11.0.0
|
||||||
|
- dependency-name: react-error-boundary
|
||||||
|
versions:
|
||||||
|
- 3.1.0
|
||||||
|
- dependency-name: jquery
|
||||||
|
versions:
|
||||||
|
- 3.5.0
|
4
superset-frontend/temporary_superset_ui/superset-ui/.github/issue_label_bot.yaml
vendored
Normal file
4
superset-frontend/temporary_superset_ui/superset-ui/.github/issue_label_bot.yaml
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
label-alias:
|
||||||
|
bug: '#bug'
|
||||||
|
feature_request: '#enhancement'
|
||||||
|
question: '#question'
|
|
@ -0,0 +1,2 @@
|
||||||
|
# Always validate the PR title, and ignore the commits
|
||||||
|
titleOnly: true
|
44
superset-frontend/temporary_superset_ui/superset-ui/.github/workflows/chromatic.yml
vendored
Normal file
44
superset-frontend/temporary_superset_ui/superset-ui/.github/workflows/chromatic.yml
vendored
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
name: Upload Chomatic Build
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_run:
|
||||||
|
workflows: ['build-and-test-workflow']
|
||||||
|
types:
|
||||||
|
- completed
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
upload:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
if: >
|
||||||
|
${{ github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion
|
||||||
|
== 'success' }}
|
||||||
|
steps:
|
||||||
|
- name: 'Download artifact'
|
||||||
|
uses: actions/github-script@v3.1.0
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
var artifacts = await github.actions.listWorkflowRunArtifacts({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
run_id: ${{github.event.workflow_run.id }},
|
||||||
|
});
|
||||||
|
var matchArtifact = artifacts.data.artifacts.filter((artifact) => {
|
||||||
|
return artifact.name == "storybookBuild"
|
||||||
|
})[0];
|
||||||
|
var download = await github.actions.downloadArtifact({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
artifact_id: matchArtifact.id,
|
||||||
|
archive_format: 'zip',
|
||||||
|
});
|
||||||
|
var fs = require('fs');
|
||||||
|
fs.writeFileSync('${{github.workspace}}/storybookBuild.zip', Buffer.from(download.data));
|
||||||
|
- run: unzip storybookBuild.zip
|
||||||
|
- name: Deploy to Chromatic
|
||||||
|
uses: chromaui/action@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
|
||||||
|
storybookBuildDir: storybookBuild
|
||||||
|
# uncomment to automatically accept all chromatic changes
|
||||||
|
# autoAcceptChanges: true
|
69
superset-frontend/temporary_superset_ui/superset-ui/.github/workflows/ci.yml
vendored
Normal file
69
superset-frontend/temporary_superset_ui/superset-ui/.github/workflows/ci.yml
vendored
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
name: build-and-test-workflow
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- '*'
|
||||||
|
tags-ignore:
|
||||||
|
- 'trigger-patch-test.*'
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Build and test
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
env:
|
||||||
|
CODECOV_TOKEN: '${{ secrets.CODECOV_TOKEN }}'
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [16]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
# pulls all commits (needed for lerna / semantic release to correctly version)
|
||||||
|
fetch-depth: '0'
|
||||||
|
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
|
||||||
|
- name: Cache npm
|
||||||
|
uses: actions/cache@v1
|
||||||
|
with:
|
||||||
|
path: ~/.npm # npm cache files are stored in `~/.npm` on Linux/macOS
|
||||||
|
key: ${{ runner.OS }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.OS }}-node-
|
||||||
|
${{ runner.OS }}-
|
||||||
|
|
||||||
|
- name: Get npm cache directory path
|
||||||
|
id: npm-cache-dir-path
|
||||||
|
run: echo "::set-output name=dir::$(npm config get cache)"
|
||||||
|
- name: Cache npm
|
||||||
|
uses: actions/cache@v1
|
||||||
|
id: npm-cache # use this to check for `cache-hit` (`steps.npm-cache.outputs.cache-hit != 'true'`)
|
||||||
|
with:
|
||||||
|
path: ${{ steps.npm-cache-dir-path.outputs.dir }}
|
||||||
|
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-npm-
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
- name: Run ESLint
|
||||||
|
run: npm run lint --quiet
|
||||||
|
- name: Build packages
|
||||||
|
run: npm run build
|
||||||
|
- name: Run unit tests
|
||||||
|
run: npm run test
|
||||||
|
- name: Build Storybook
|
||||||
|
run: npm run build-storybook
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: storybookBuild
|
||||||
|
path: ./packages/superset-ui-demo/storybook-static/
|
||||||
|
|
||||||
|
- name: Report code coverage
|
||||||
|
run: .github/workflows/codecov.sh
|
1903
superset-frontend/temporary_superset_ui/superset-ui/.github/workflows/codecov.sh
vendored
Executable file
1903
superset-frontend/temporary_superset_ui/superset-ui/.github/workflows/codecov.sh
vendored
Executable file
File diff suppressed because it is too large
Load Diff
82
superset-frontend/temporary_superset_ui/superset-ui/.github/workflows/release.yml
vendored
Normal file
82
superset-frontend/temporary_superset_ui/superset-ui/.github/workflows/release.yml
vendored
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
name: release-workflow
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- 'master'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
name: Bump version and publish package(s)
|
||||||
|
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
node-version: [16]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
# pulls all commits (needed for lerna / semantic release to correctly version)
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: Get tags and filter trigger tags
|
||||||
|
run: |
|
||||||
|
git fetch --depth=1 origin "+refs/tags/*:refs/tags/*"
|
||||||
|
git fetch --prune --unshallow
|
||||||
|
git tag -d `git tag | grep -E '^trigger-'`
|
||||||
|
|
||||||
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: ${{ matrix.node-version }}
|
||||||
|
|
||||||
|
- name: Cache npm
|
||||||
|
uses: actions/cache@v1
|
||||||
|
with:
|
||||||
|
path: ~/.npm # npm cache files are stored in `~/.npm` on Linux/macOS
|
||||||
|
key: ${{ runner.OS }}-node-${{ hashFiles('**/package-lock.json') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.OS }}-node-
|
||||||
|
${{ runner.OS }}-
|
||||||
|
|
||||||
|
- name: Get npm cache directory path
|
||||||
|
id: npm-cache-dir-path
|
||||||
|
run: echo "::set-output name=dir::$(npm config get cache)"
|
||||||
|
- name: Cache npm
|
||||||
|
uses: actions/cache@v1
|
||||||
|
id: npm-cache # use this to check for `cache-hit` (`steps.npm-cache.outputs.cache-hit != 'true'`)
|
||||||
|
with:
|
||||||
|
path: ${{ steps.npm-cache-dir-path.outputs.dir }}
|
||||||
|
key: ${{ runner.os }}-npm-${{ hashFiles('**/package-lock.json') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-npm-
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm ci
|
||||||
|
- name: Build packages
|
||||||
|
run: npm run build
|
||||||
|
- name: Run unit tests
|
||||||
|
run: npm run test
|
||||||
|
|
||||||
|
- name: Configure npm and git
|
||||||
|
run: |
|
||||||
|
echo "@superset-ui:registry=https://registry.npmjs.org/" > .npmrc
|
||||||
|
echo "registry=https://registry.npmjs.org/" >> .npmrc
|
||||||
|
echo "//registry.npmjs.org/:_authToken=\${NPM_TOKEN}" >> $HOME/.npmrc 2> /dev/null
|
||||||
|
npm whoami
|
||||||
|
git config --local user.email "action@github.com"
|
||||||
|
git config --local user.name "GitHub Action"
|
||||||
|
git remote set-url origin "https://${GITHUB_TOKEN}@github.com/apache-superset/superset-ui.git" > /dev/null 2>&1
|
||||||
|
env:
|
||||||
|
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Bump version and publish package(s)
|
||||||
|
run: |
|
||||||
|
git tag -d `git tag | grep -E '^trigger-'`
|
||||||
|
npm run ci:release-from-tag
|
||||||
|
env:
|
||||||
|
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
GH_TOKEN: ${{ secrets.GH_PERSONAL_ACCESS_TOKEN }}
|
|
@ -0,0 +1,49 @@
|
||||||
|
.DS_Store
|
||||||
|
*.DS_Store
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs/
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Cache
|
||||||
|
.bundle/
|
||||||
|
.happo/
|
||||||
|
.idea/
|
||||||
|
.next/
|
||||||
|
.cache
|
||||||
|
.eslintcache
|
||||||
|
.idea
|
||||||
|
*.iml
|
||||||
|
.npm
|
||||||
|
.npmrc
|
||||||
|
.vscode
|
||||||
|
.yarnclean
|
||||||
|
|
||||||
|
# Directories
|
||||||
|
build/
|
||||||
|
coverage/
|
||||||
|
dist/
|
||||||
|
esm/
|
||||||
|
lib/
|
||||||
|
public/
|
||||||
|
node_modules/
|
||||||
|
tmp/
|
||||||
|
_gh-pages/
|
||||||
|
|
||||||
|
# Custom
|
||||||
|
*.map
|
||||||
|
*.min.js
|
||||||
|
test-changelog.md
|
||||||
|
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# Ignore package-lock in packages
|
||||||
|
plugins/*/package-lock.json
|
||||||
|
packages/*/package-lock.json
|
||||||
|
|
||||||
|
# For country map geojson conversion script
|
||||||
|
.ipynb_checkpoints/
|
||||||
|
scripts/*.zip
|
||||||
|
|
||||||
|
**/storybook-static
|
||||||
|
rat-results.txt
|
|
@ -0,0 +1 @@
|
||||||
|
v14.15.5
|
|
@ -0,0 +1,17 @@
|
||||||
|
_gh-pages/
|
||||||
|
coverage/
|
||||||
|
node_modules/
|
||||||
|
public/
|
||||||
|
esm/
|
||||||
|
lib/
|
||||||
|
tmp/
|
||||||
|
dist/
|
||||||
|
lerna.json
|
||||||
|
npm-shrinkwrap.json
|
||||||
|
package-lock.json
|
||||||
|
tsconfig.json
|
||||||
|
tsconfig.options.json
|
||||||
|
tsconfig.eslint.json
|
||||||
|
CHANGELOG.md
|
||||||
|
*.geojson
|
||||||
|
*-topo.json
|
|
@ -0,0 +1,66 @@
|
||||||
|
# Note: these patterns are applied to single files or directories, not full paths
|
||||||
|
.gitignore
|
||||||
|
docs/README.md
|
||||||
|
.gitattributes
|
||||||
|
.gitkeep
|
||||||
|
.coverage
|
||||||
|
.coveragerc
|
||||||
|
.codecov.yml
|
||||||
|
.eslintrc
|
||||||
|
.eslintignore
|
||||||
|
.flake8
|
||||||
|
.nvmrc
|
||||||
|
.prettierrc
|
||||||
|
.rat-excludes
|
||||||
|
.*log
|
||||||
|
.*pyc
|
||||||
|
.*lock
|
||||||
|
.*geojson
|
||||||
|
DISCLAIMER
|
||||||
|
licenses/*
|
||||||
|
node_modules/*
|
||||||
|
rat-results.txt
|
||||||
|
babel-node
|
||||||
|
dist
|
||||||
|
superset/static/*
|
||||||
|
build
|
||||||
|
superset.egg-info
|
||||||
|
apache_superset.egg-info
|
||||||
|
.idea
|
||||||
|
.*sql
|
||||||
|
.*zip
|
||||||
|
.*lock
|
||||||
|
# json and csv in general cannot have comments
|
||||||
|
.*json
|
||||||
|
.*csv
|
||||||
|
# Generated doc files
|
||||||
|
env/*
|
||||||
|
docs/README.md
|
||||||
|
docs/.htaccess*
|
||||||
|
_build/*
|
||||||
|
_static/*
|
||||||
|
.buildinfo
|
||||||
|
searchindex.js
|
||||||
|
# auto generated
|
||||||
|
requirements/*
|
||||||
|
# vendorized
|
||||||
|
vendor/*
|
||||||
|
# github configuration
|
||||||
|
.github/*
|
||||||
|
.*mdx
|
||||||
|
coverage/*
|
||||||
|
.*.md
|
||||||
|
.*.txt
|
||||||
|
|
||||||
|
# skip license check in superset-ui
|
||||||
|
tmp/*
|
||||||
|
lib/*
|
||||||
|
esm/*
|
||||||
|
tsconfig.tsbuildinfo
|
||||||
|
.*ipynb
|
||||||
|
.*yml
|
||||||
|
.*iml
|
||||||
|
.esprintrc
|
||||||
|
.prettierignore
|
||||||
|
README.erb
|
||||||
|
package.erb
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,71 @@
|
||||||
|
## Contributing guidelines
|
||||||
|
|
||||||
|
### Setup local development
|
||||||
|
|
||||||
|
1. clone this repo
|
||||||
|
2. have `npm` install package dependencies and manage the symlinking between packages for you
|
||||||
|
|
||||||
|
```sh
|
||||||
|
git clone ...superset-ui && cd superset-ui
|
||||||
|
npm ci
|
||||||
|
npm build
|
||||||
|
```
|
||||||
|
|
||||||
|
To build only selected packages or plugins,
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm build "*chart-table"
|
||||||
|
```
|
||||||
|
|
||||||
|
### File organization
|
||||||
|
|
||||||
|
[lerna](https://github.com/lerna/lerna/) and [npm](https://www.npmjs.com/) are used to manage
|
||||||
|
versions and dependencies between packages in this monorepo.
|
||||||
|
|
||||||
|
```
|
||||||
|
superset-ui/
|
||||||
|
lerna.json
|
||||||
|
package.json
|
||||||
|
...
|
||||||
|
packages/
|
||||||
|
package1/
|
||||||
|
package.json
|
||||||
|
...
|
||||||
|
src/
|
||||||
|
test/ # unit tests
|
||||||
|
types/ # typescript type declarations
|
||||||
|
...
|
||||||
|
lib/ # commonjs output
|
||||||
|
esm/ # es module output
|
||||||
|
...
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
### Builds, linting, and testing
|
||||||
|
|
||||||
|
Each package defines its own build config, linting, and testing. You can have lerna run commands
|
||||||
|
across all packages using the syntax `npm run test` (or `npm run test:watch` for watch mode) from
|
||||||
|
the root `@superset-ui` directory.
|
||||||
|
|
||||||
|
- [Using Storybook](docs/storybook.md) - You can test your components independently from Superset
|
||||||
|
app.
|
||||||
|
- [Debugging Superset plugins in Superset app](docs/debugging.md) - Sometimes something went wrong
|
||||||
|
and you have to do it.
|
||||||
|
|
||||||
|
### Committing
|
||||||
|
|
||||||
|
This repository follows
|
||||||
|
[conventional commits](https://www.conventionalcommits.org/en/v1.0.0-beta.3/) guideline for commit
|
||||||
|
messages and has a `commitlint` hook which will require you to have the valid commit message before
|
||||||
|
committing. You can use `npm run commit` to help you create a commit message.
|
||||||
|
|
||||||
|
### Publishing
|
||||||
|
|
||||||
|
**Prerequisite:** You'll need to be a committer on the `apache-superset` organization to be able to
|
||||||
|
publish new versions of `superset-ui`.
|
||||||
|
|
||||||
|
1. Checkout the `master` branch from the main repo at `apache-superset/superset-ui` - NOT A FORK!
|
||||||
|
2. run `npm run ci:create-patch-version` to bump the patch version (the most common case) or
|
||||||
|
`npm run ci:create-minor-version` to bump the minor version. Once the process finishes and the
|
||||||
|
commit has been pushed to GitHub, CI will complete publishing the release to npm (takes some time
|
||||||
|
to complete).
|
|
@ -0,0 +1,201 @@
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
|
@ -0,0 +1,80 @@
|
||||||
|
# @superset-ui
|
||||||
|
|
||||||
|
[![Codecov branch](https://img.shields.io/codecov/c/github/apache-superset/superset-ui/master.svg?style=flat-square)](https://codecov.io/gh/apache-superset/superset-ui/branch/master)
|
||||||
|
[![Build Status](https://img.shields.io/travis/com/apache-superset/superset-ui/master.svg?style=flat-square)](https://travis-ci.com/apache-superset/superset-ui)
|
||||||
|
[![David](https://img.shields.io/david/dev/apache-superset/superset-ui.svg?style=flat-square)](https://david-dm.org/apache-superset/superset-ui?type=dev)
|
||||||
|
|
||||||
|
Collection of packages that power the
|
||||||
|
[Apache Superset](https://github.com/apache/incubator-superset) UI, and can be used to craft custom
|
||||||
|
data applications that leverage a Superset backend :chart_with_upwards_trend:
|
||||||
|
|
||||||
|
## Demo
|
||||||
|
|
||||||
|
Most recent release: https://apache-superset.github.io/superset-ui/
|
||||||
|
|
||||||
|
Current master: https://superset-ui.now.sh/
|
||||||
|
|
||||||
|
## Packages
|
||||||
|
|
||||||
|
### Core packages
|
||||||
|
|
||||||
|
| Package | Version |
|
||||||
|
| ----------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| [@superset-ui/core](https://github.com/apache-superset/superset-ui/tree/master/packages/superset-ui-core) | [![Version](https://img.shields.io/npm/v/@superset-ui/core.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/core) |
|
||||||
|
| [@superset-ui/chart-controls](https://github.com/apache-superset/superset-ui/tree/master/packages/superset-ui-chart-controls) | [![Version](https://img.shields.io/npm/v/@superset-ui/core.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/chart-controls) |
|
||||||
|
| [@superset-ui/generator-superset](https://github.com/apache-superset/superset-ui/tree/master/packages/generator-superset) | [![Version](https://img.shields.io/npm/v/@superset-ui/generator-superset.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/generator-superset) |
|
||||||
|
|
||||||
|
### Chart plugin packages
|
||||||
|
|
||||||
|
`@superset-ui/legacy-*` packages are extracted from the classic
|
||||||
|
[Apache Superset](https://github.com/apache/incubator-superset) and converted into plugins. These
|
||||||
|
packages are extracted with minimal changes (almost as-is). They also depend on legacy API
|
||||||
|
(`viz.py`) to function.
|
||||||
|
|
||||||
|
| Package | Version |
|
||||||
|
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| [@superset-ui/legacy-preset-chart-big-number](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-preset-chart-big-number) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-preset-chart-big-number.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-preset-chart-big-number) |
|
||||||
|
| [@superset-ui/legacy-preset-chart-nvd3](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-preset-chart-nvd3) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-preset-chart-nvd3.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-preset-chart-nvd3) |
|
||||||
|
| [@superset-ui/legacy-plugin-chart-calendar](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-calendar) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-calendar.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-calendar) |
|
||||||
|
| [@superset-ui/legacy-plugin-chart-chord](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-chord) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-chord.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-chord) |
|
||||||
|
| [@superset-ui/legacy-plugin-chart-country-map](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-country-map) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-country-map.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-country-map) |
|
||||||
|
| [@superset-ui/legacy-plugin-chart-event-flow](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-event-flow) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-event-flow.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-event-flow) |
|
||||||
|
| [@superset-ui/legacy-plugin-chart-force-directed](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-force-directed) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-force-directed.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-force-directed) |
|
||||||
|
| [@superset-ui/legacy-plugin-chart-heatmap](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-heatmap) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-heatmap.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-heatmap) |
|
||||||
|
| [@superset-ui/legacy-plugin-chart-histogram](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-histogram) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-histogram.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-histogram) |
|
||||||
|
| [@superset-ui/legacy-plugin-chart-horizon](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-horizon) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-horizon.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-horizon) |
|
||||||
|
| [@superset-ui/legacy-plugin-chart-iframe](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-iframe) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-iframe.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-iframe) |
|
||||||
|
| [@superset-ui/legacy-plugin-chart-markup](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-markup) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-markup.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-markup) |
|
||||||
|
| [@superset-ui/legacy-plugin-chart-map-box](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-map-box) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-map-box.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-map-box) |
|
||||||
|
| [@superset-ui/legacy-plugin-chart-paired-t-test](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-paired-t-test) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-paired-t-test.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-paired-t-test) |
|
||||||
|
| [@superset-ui/legacy-plugin-chart-parallel-coordinates](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-parallel-coordinates) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-parallel-coordinates.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-parallel-coordinates) |
|
||||||
|
| [@superset-ui/legacy-plugin-chart-partition](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-partition) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-partition.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-partition) |
|
||||||
|
| [@superset-ui/legacy-plugin-chart-pivot-table](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-pivot-table) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-pivot-table.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-pivot-table) |
|
||||||
|
| [@superset-ui/legacy-plugin-chart-rose](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-rose) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-rose.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-rose) |
|
||||||
|
| [@superset-ui/legacy-plugin-chart-sankey](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-sankey) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-sankey.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-sankey) |
|
||||||
|
| [@superset-ui/legacy-plugin-chart-sankey-loop](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-sankey-loop) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-sankey-loop.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-sankey-loop) |
|
||||||
|
| [@superset-ui/legacy-plugin-chart-sunburst](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-sunburst) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-sunburst.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-sunburst) |
|
||||||
|
| [@superset-ui/legacy-plugin-chart-treemap](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-treemap) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-treemap.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-treemap) |
|
||||||
|
| [@superset-ui/legacy-plugin-chart-world-map](https://github.com/apache-superset/superset-ui/tree/master/plugins/legacy-plugin-chart-world-map) | [![Version](https://img.shields.io/npm/v/@superset-ui/legacy-plugin-chart-world-map.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/legacy-plugin-chart-world-map) |
|
||||||
|
|
||||||
|
`@superset-ui/plugin-*` packages are newer and higher quality in general. A key difference that they
|
||||||
|
do not depend on `viz.py` (which contain visualization-specific python code) and interface with
|
||||||
|
`/api/v1/query/`, a new generic endpoint instead meant to serve all visualizations, instead. Also
|
||||||
|
should be written in Typescript.
|
||||||
|
|
||||||
|
| Package | Version | Note |
|
||||||
|
| ---------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---- |
|
||||||
|
| [@superset-ui/plugin-chart-word-cloud](https://github.com/apache-superset/superset-ui/tree/master/plugins/plugin-chart-word-cloud) | [![Version](https://img.shields.io/npm/v/@superset-ui/plugin-chart-word-cloud.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/plugin-chart-word-cloud) | |
|
||||||
|
| [@superset-ui/plugin-chart-table](https://github.com/apache-superset/superset-ui/tree/master/plugins/plugin-chart-table) | [![Version](https://img.shields.io/npm/v/@superset-ui/plugin-chart-table.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/plugin-chart-table) | |
|
||||||
|
| [@superset-ui/preset-chart-xy](https://github.com/apache-superset/superset-ui/tree/master/plugins/preset-chart-xy) | [![Version](https://img.shields.io/npm/v/@superset-ui/preset-chart-xy.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/preset-chart-xy) | |
|
||||||
|
| [@superset-ui/plugin-chart-echarts](https://github.com/apache-superset/superset-ui/tree/master/plugins/plugin-chart-echarts) | [![Version](https://img.shields.io/npm/v/@superset-ui/plugin-chart-echarts.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/plugin-chart-echarts) | |
|
||||||
|
| [@superset-ui/plugin-filter-antd](https://github.com/apache-superset/superset-ui/tree/master/plugins/plugin-filter-antd) | [![Version](https://img.shields.io/npm/v/@superset-ui/plugin-chart-echarts.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/plugin-filter-antd) | |
|
||||||
|
|
||||||
|
## Contribution and development guide
|
||||||
|
|
||||||
|
Please read the [contributing guidelines](CONTRIBUTING.md) which include development environment
|
||||||
|
setup and other things you should know about coding in this repo.
|
||||||
|
|
||||||
|
### License
|
||||||
|
|
||||||
|
Apache-2.0
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const { getConfig } = require('@airbnb/config-babel');
|
||||||
|
|
||||||
|
const config = getConfig({
|
||||||
|
library: true,
|
||||||
|
react: true,
|
||||||
|
next: true,
|
||||||
|
esm: process.env.BABEL_OUTPUT === 'esm',
|
||||||
|
node: process.env.NODE_ENV === 'test',
|
||||||
|
typescript: true,
|
||||||
|
env: {
|
||||||
|
targets: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Override to allow transpile es modules inside vega-lite
|
||||||
|
config.ignore = config.ignore.filter(item => item !== 'node_modules/');
|
||||||
|
config.ignore.push('node_modules/(?!(vega-lite|lodash-es))');
|
||||||
|
config.plugins = [
|
||||||
|
['babel-plugin-transform-dev', { evaluate: false }],
|
||||||
|
['babel-plugin-typescript-to-proptypes', { loose: true }],
|
||||||
|
['@babel/plugin-proposal-class-properties', { loose: true }],
|
||||||
|
];
|
||||||
|
config.presets.push([
|
||||||
|
'@emotion/babel-preset-css-prop',
|
||||||
|
{
|
||||||
|
autoLabel: 'dev-only',
|
||||||
|
labelFormat: '[local]',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
module.exports = config;
|
|
@ -0,0 +1,22 @@
|
||||||
|
coverage:
|
||||||
|
status:
|
||||||
|
patch: off
|
||||||
|
project:
|
||||||
|
default:
|
||||||
|
target: 0%
|
||||||
|
threshold: 10%
|
||||||
|
core-packages-ts:
|
||||||
|
target: 100%
|
||||||
|
paths:
|
||||||
|
- 'packages'
|
||||||
|
- '!packages/**/*.jsx'
|
||||||
|
- '!packages/**/*.tsx'
|
||||||
|
core-packages-tsx:
|
||||||
|
target: 50%
|
||||||
|
paths:
|
||||||
|
- 'packages/**/*.jsx'
|
||||||
|
- 'packages/**/*.tsx'
|
||||||
|
plugins:
|
||||||
|
target: 0
|
||||||
|
paths:
|
||||||
|
- plugins
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
extends: [
|
||||||
|
'@commitlint/config-conventional',
|
||||||
|
'@commitlint/config-lerna-scopes',
|
||||||
|
],
|
||||||
|
};
|
|
@ -0,0 +1,27 @@
|
||||||
|
# Debug Superset plugins in Superset app
|
||||||
|
|
||||||
|
## Activate plugins for local development
|
||||||
|
|
||||||
|
1. First, make sure you have run `npm ci` and `npm run build` in `superset-ui` or your own plugin
|
||||||
|
repo.
|
||||||
|
2. Go to [superset-frontend](https://github.com/apache/superset/tree/master/superset-frontend), use
|
||||||
|
`npm link` to create a symlink of the plugin source code in `node_modules`:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd superset/superset-frontend
|
||||||
|
# npm link ~/path/to/your/plugin
|
||||||
|
npm link ../../superset-ui/plugins/plugin-chart-word-cloud
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Start developing with webpack dev server:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm run dev-server
|
||||||
|
```
|
||||||
|
|
||||||
|
The dev server will automatically build from the source code under `path/to/your-plugin/src` and
|
||||||
|
watch the changes.
|
||||||
|
|
||||||
|
## Deactivate plugins
|
||||||
|
|
||||||
|
To deactivate a plugin, simply run `npm ci` in `superset/superset-frontend` again.
|
|
@ -0,0 +1,13 @@
|
||||||
|
## Using Storybook
|
||||||
|
|
||||||
|
You can demo your changes by running the storybook demo locally with the following commands:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm ci
|
||||||
|
npm run build
|
||||||
|
npm run storybook
|
||||||
|
```
|
||||||
|
|
||||||
|
The Storybook will
|
||||||
|
[automatically build from the source code](https://github.com/apache-superset/superset-ui/blob/master/packages/superset-ui-demo/.storybook/main.js#L49-L58)
|
||||||
|
when package names start with `@superset-ui/`.
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
bail: false,
|
||||||
|
collectCoverageFrom: [
|
||||||
|
'**/src/**/*.{ts,tsx,js,jsx}',
|
||||||
|
'**/test/**/*.{ts,tsx,js,jsx}',
|
||||||
|
],
|
||||||
|
coverageDirectory: './coverage',
|
||||||
|
coveragePathIgnorePatterns: [
|
||||||
|
'coverage/',
|
||||||
|
'node_modules/',
|
||||||
|
'public/',
|
||||||
|
'esm/',
|
||||||
|
'lib/',
|
||||||
|
'tmp/',
|
||||||
|
'dist/',
|
||||||
|
],
|
||||||
|
coverageReporters: ['lcov', 'json-summary', 'html'],
|
||||||
|
coverageThreshold: {
|
||||||
|
global: {
|
||||||
|
branches: 0,
|
||||||
|
functions: 0,
|
||||||
|
lines: 0,
|
||||||
|
statements: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
globals: {
|
||||||
|
__DEV__: true,
|
||||||
|
caches: true,
|
||||||
|
},
|
||||||
|
moduleFileExtensions: ['mock.js', 'ts', 'tsx', 'js', 'jsx', 'json', 'node'],
|
||||||
|
moduleNameMapper: {
|
||||||
|
'\\.(css|less|geojson)$': '<rootDir>/test/__mocks__/mockExportObject.js',
|
||||||
|
'\\.(gif|ttf|eot|png|jpg)$': '<rootDir>/test/__mocks__/mockExportString.js',
|
||||||
|
'\\.svg$': '<rootDir>/test/__mocks__/svgrMock.tsx',
|
||||||
|
'@superset-ui/(((?!(legacy-preset-chart-deckgl|core/src)).)*)$':
|
||||||
|
'<rootDir>/node_modules/@superset-ui/$1/src',
|
||||||
|
'@superset-ui/core/src/(.*)$':
|
||||||
|
'<rootDir>/node_modules/@superset-ui/core/src/$1',
|
||||||
|
},
|
||||||
|
roots: ['<rootDir>/packages', '<rootDir>/plugins'],
|
||||||
|
setupFiles: ['<rootDir>/test/setup.ts'],
|
||||||
|
testEnvironment: 'jsdom',
|
||||||
|
testURL: 'http://localhost',
|
||||||
|
timers: 'real',
|
||||||
|
verbose: false,
|
||||||
|
transformIgnorePatterns: ['node_modules/(?!(vega-lite|lodash-es))'],
|
||||||
|
testPathIgnorePatterns: ['packages/generator-superset/generators'],
|
||||||
|
projects: [
|
||||||
|
'<rootDir>',
|
||||||
|
{
|
||||||
|
displayName: 'node',
|
||||||
|
rootDir: '<rootDir>/packages/generator-superset',
|
||||||
|
testMatch: ['<rootDir>/test/**/?(*.)+(spec|test).{js,jsx,ts,tsx}'],
|
||||||
|
testEnvironment: 'node',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
snapshotSerializers: ['@emotion/jest/enzyme-serializer'],
|
||||||
|
};
|
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"lerna": "3.2.1",
|
||||||
|
"npmClient": "npm",
|
||||||
|
"packages": [
|
||||||
|
"packages/*",
|
||||||
|
"plugins/*"
|
||||||
|
],
|
||||||
|
"useWorkspaces": true,
|
||||||
|
"version": "0.18.25",
|
||||||
|
"ignoreChanges": [
|
||||||
|
"**/*.md",
|
||||||
|
"**/*.spec.tsx?",
|
||||||
|
"**/*.spec.jsx?",
|
||||||
|
"**/__mocks__/**"
|
||||||
|
],
|
||||||
|
"command": {
|
||||||
|
"publish": {
|
||||||
|
"message": "chore: publish %s",
|
||||||
|
"graphType": "all"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"message": "chore: publish %s",
|
||||||
|
"exact": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,167 @@
|
||||||
|
{
|
||||||
|
"name": "@superset-ui/monorepo",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"description": "Superset UI",
|
||||||
|
"private": true,
|
||||||
|
"scripts": {
|
||||||
|
"build": "node ./scripts/build.js",
|
||||||
|
"build:assets": "node ./scripts/copyAssets.js",
|
||||||
|
"babel": "npm run build --no-type",
|
||||||
|
"demo": "cd packages/superset-ui-demo && npm run demo:build",
|
||||||
|
"demo:clean": "cd packages/superset-ui-demo && npm run demo:clean",
|
||||||
|
"demo:build": "cd packages/superset-ui-demo && npm run demo:build",
|
||||||
|
"storybook": "cd packages/superset-ui-demo && npm run storybook",
|
||||||
|
"build-storybook": "cd packages/superset-ui-demo && npm run build-storybook",
|
||||||
|
"chromatic": "cd packages/superset-ui-demo && npm run chromatic",
|
||||||
|
"sb": "npm run storybook",
|
||||||
|
"clean": "npm run build --clean --no-babel --no-type",
|
||||||
|
"commit": "superset-commit",
|
||||||
|
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 10",
|
||||||
|
"jest": "NODE_ENV=test jest --coverage --verbose",
|
||||||
|
"lint": "eslint --ignore-path=.eslintignore --ext .js,.jsx,.ts,.tsx .",
|
||||||
|
"lint:fix": "eslint --fix --ignore-path=.eslintignore --ext .js,.jsx,.ts,.tsx .",
|
||||||
|
"format": "npm run prettier",
|
||||||
|
"prettier": "prettier --write './{plugins,packages}/**/*{.js,.jsx,.ts,.tsx,.css,.less,.scss,.sass}'",
|
||||||
|
"test": "npm run jest",
|
||||||
|
"test:watch": "npm run lint:fix && npm run jest --watch",
|
||||||
|
"type": "npm run build --no-babel",
|
||||||
|
"prepare-release": "git checkout master && git pull --rebase origin master && npm run install && npm run test",
|
||||||
|
"prerelease": "npm run build",
|
||||||
|
"release": "npm run prepare-release && lerna publish && npm run postrelease",
|
||||||
|
"postrelease": "lerna run deploy-demo",
|
||||||
|
"list-changed-packages": "lerna changed",
|
||||||
|
"manual-release": "lerna publish --force-publish && npm run postrelease",
|
||||||
|
"clean-npm-lock": "rm -rf ./{packages,plugins}/*/package-lock.json",
|
||||||
|
"prune": "rm -rf ./{packages,plugins}/*/{lib,esm,tsconfig.tsbuildinfo}",
|
||||||
|
"ci:create-patch-version": "npm run clean-npm-lock && ./scripts/lernaVersion.sh patch",
|
||||||
|
"ci:create-minor-version": "npm run clean-npm-lock && ./scripts/lernaVersion.sh minor",
|
||||||
|
"ci:create-conventional-version": "npm run clean-npm-lock && ./scripts/lernaVersion.sh '--conventional-commits --create-release github'",
|
||||||
|
"ci:release-from-tag": "npm run clean-npm-lock && lerna publish from-package --yes",
|
||||||
|
"ci:release-conventional": "npm run clean-npm-lock && lerna publish --conventional-commits --create-release github --yes"
|
||||||
|
},
|
||||||
|
"repository": "https://github.com/apache-superset/superset-ui.git",
|
||||||
|
"keywords": [
|
||||||
|
"apache",
|
||||||
|
"superset",
|
||||||
|
"data",
|
||||||
|
"analytics",
|
||||||
|
"analysis",
|
||||||
|
"visualization",
|
||||||
|
"react",
|
||||||
|
"d3",
|
||||||
|
"data-ui",
|
||||||
|
"vx"
|
||||||
|
],
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"dependencies": {
|
||||||
|
"@airbnb/config-babel": "^3.1.0",
|
||||||
|
"@airbnb/config-jest": "^3.0.2",
|
||||||
|
"@airbnb/config-webpack": "^3.3.1",
|
||||||
|
"@babel/cli": "^7.11.5",
|
||||||
|
"@babel/compat-data": "^7.9.6",
|
||||||
|
"@babel/core": "^7.8.7",
|
||||||
|
"@babel/eslint-parser": "^7.16.0",
|
||||||
|
"@babel/node": "^7.8.7",
|
||||||
|
"@babel/plugin-proposal-class-properties": "^7.8.3",
|
||||||
|
"@babel/plugin-proposal-optional-chaining": "^7.8.3",
|
||||||
|
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||||
|
"@babel/plugin-transform-runtime": "^7.8.3",
|
||||||
|
"@babel/preset-env": "^7.8.7",
|
||||||
|
"@babel/preset-react": "^7.8.3",
|
||||||
|
"@babel/preset-typescript": "^7.12.7",
|
||||||
|
"@babel/register": "^7.8.6",
|
||||||
|
"@emotion/babel-preset-css-prop": "^11.2.0",
|
||||||
|
"@emotion/jest": "^11.3.0",
|
||||||
|
"@storybook/preset-typescript": "^3.0.0",
|
||||||
|
"@superset-ui/commit-config": "^0.0.9",
|
||||||
|
"@types/enzyme": "^3.10.3",
|
||||||
|
"@types/jest": "^26.0.4",
|
||||||
|
"@types/jsdom": "^12.2.4",
|
||||||
|
"@types/react": "^16.13.1",
|
||||||
|
"@types/react-test-renderer": "^16.9.2",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.3.0",
|
||||||
|
"@typescript-eslint/parser": "^5.3.0",
|
||||||
|
"babel-eslint": "^10.1.0",
|
||||||
|
"babel-jest": "^26.6.3",
|
||||||
|
"babel-loader": "^8.2.2",
|
||||||
|
"babel-plugin-dynamic-import-node": "^2.3.3",
|
||||||
|
"babel-plugin-jsx-remove-data-test-id": "^2.1.3",
|
||||||
|
"babel-plugin-lodash": "^3.3.4",
|
||||||
|
"babel-plugin-typescript-to-proptypes": "^1.4.2",
|
||||||
|
"enzyme": "^3.11.0",
|
||||||
|
"enzyme-adapter-react-16": "^1.15.1",
|
||||||
|
"enzyme-to-json": "^3.4.3",
|
||||||
|
"eslint": "^7.32.0",
|
||||||
|
"eslint-config-airbnb": "^18.2.1",
|
||||||
|
"eslint-config-prettier": "^7.1.0",
|
||||||
|
"eslint-import-resolver-typescript": "^2.3.0",
|
||||||
|
"eslint-import-resolver-webpack": "^0.13.0",
|
||||||
|
"eslint-plugin-cypress": "^2.11.2",
|
||||||
|
"eslint-plugin-import": "^2.22.1",
|
||||||
|
"eslint-plugin-jest": "^24.1.3",
|
||||||
|
"eslint-plugin-jest-dom": "^3.6.5",
|
||||||
|
"eslint-plugin-jsx-a11y": "^6.4.1",
|
||||||
|
"eslint-plugin-no-only-tests": "^2.4.0",
|
||||||
|
"eslint-plugin-prettier": "^3.3.1",
|
||||||
|
"eslint-plugin-react": "^7.22.0",
|
||||||
|
"eslint-plugin-react-hooks": "^4.2.0",
|
||||||
|
"eslint-plugin-testing-library": "^3.10.1",
|
||||||
|
"eslint-plugin-unicorn": "^25.0.1",
|
||||||
|
"esprint": "^0.7.0",
|
||||||
|
"fast-glob": "^3.2.4",
|
||||||
|
"fs-extra": "^9.0.0",
|
||||||
|
"global-box": "^1.2.0",
|
||||||
|
"husky": "^4.2.5",
|
||||||
|
"identity-obj-proxy": "^3.0.0",
|
||||||
|
"jest": "^26.6.3",
|
||||||
|
"jest-environment-enzyme": "^7.1.2",
|
||||||
|
"jest-enzyme": "^7.1.2",
|
||||||
|
"jest-mock-console": "^1.0.0",
|
||||||
|
"jsdom": "^16.4.0",
|
||||||
|
"lerna": "^3.15.0",
|
||||||
|
"lint-staged": "^10.0.3",
|
||||||
|
"npm": "^7.5.4",
|
||||||
|
"prettier": "^2.4.1",
|
||||||
|
"react": "^16.13.1",
|
||||||
|
"react-dom": "^16.13.1",
|
||||||
|
"react-loadable": "^5.5.0",
|
||||||
|
"react-test-renderer": "^16.13.1",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"semver": "^7.3.5",
|
||||||
|
"ts-jest": "^26.4.2",
|
||||||
|
"ts-loader": "^8.0.7",
|
||||||
|
"typescript": "^4.1.2",
|
||||||
|
"webpack": "^4.42.0",
|
||||||
|
"webpack-bundle-analyzer": "^3.6.1",
|
||||||
|
"webpack-cli": "^3.3.11",
|
||||||
|
"webpack-dev-server": "^3.11.0",
|
||||||
|
"webpack-manifest-plugin": "^2.2.0",
|
||||||
|
"webpack-sources": "^1.4.3",
|
||||||
|
"yargs": "^15.4.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "14.x || 16.x",
|
||||||
|
"npm": "^7.5.4"
|
||||||
|
},
|
||||||
|
"workspaces": [
|
||||||
|
"./packages/*",
|
||||||
|
"./plugins/*"
|
||||||
|
],
|
||||||
|
"browserslist": [
|
||||||
|
"last 3 chrome versions",
|
||||||
|
"last 3 firefox versions",
|
||||||
|
"last 3 safari versions",
|
||||||
|
"last 3 edge versions"
|
||||||
|
],
|
||||||
|
"husky": {
|
||||||
|
"hooks": {
|
||||||
|
"pre-commit": "lint-staged",
|
||||||
|
"commit-msg": "./scripts/commitlint.js HUSKY_GIT_PARAMS"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lint-staged": {
|
||||||
|
"*.{js,jsx,ts,tsx,json,md}": [
|
||||||
|
"prettier --write"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
* text=auto
|
|
@ -0,0 +1,27 @@
|
||||||
|
<!--
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
or more contributor license agreements. See the NOTICE file
|
||||||
|
distributed with this work for additional information
|
||||||
|
regarding copyright ownership. The ASF licenses this file
|
||||||
|
to you under the Apache License, Version 2.0 (the
|
||||||
|
"License"); you may not use this file except in compliance
|
||||||
|
with the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing,
|
||||||
|
software distributed under the License is distributed on an
|
||||||
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
KIND, either express or implied. See the License for the
|
||||||
|
specific language governing permissions and limitations
|
||||||
|
under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
# Change Log
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [0.18.0](https://github.com/apache-superset/superset-ui/compare/v0.17.87...v0.18.0) (2021-08-30)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @superset-ui/generator-superset
|
|
@ -0,0 +1,52 @@
|
||||||
|
<!--
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
or more contributor license agreements. See the NOTICE file
|
||||||
|
distributed with this work for additional information
|
||||||
|
regarding copyright ownership. The ASF licenses this file
|
||||||
|
to you under the Apache License, Version 2.0 (the
|
||||||
|
"License"); you may not use this file except in compliance
|
||||||
|
with the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing,
|
||||||
|
software distributed under the License is distributed on an
|
||||||
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
KIND, either express or implied. See the License for the
|
||||||
|
specific language governing permissions and limitations
|
||||||
|
under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
# generator-superset
|
||||||
|
|
||||||
|
[![Version](https://img.shields.io/npm/v/@superset-ui/generator-superset.svg?style=flat)](https://www.npmjs.com/package/@superset-ui/generator-superset)
|
||||||
|
[![David (path)](https://img.shields.io/david/apache-superset/superset-ui.svg?path=packages%2Fgenerator-superset&style=flat-square)](https://david-dm.org/apache-superset/superset-ui?path=packages/generator-superset)
|
||||||
|
|
||||||
|
> Scaffolder for Superset
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
First, install [Yeoman](http://yeoman.io) and `generator-superset` using
|
||||||
|
[npm](https://www.npmjs.com/) (we assume you have pre-installed [node.js](https://nodejs.org/)).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install -g yo
|
||||||
|
npm install -g @superset-ui/generator-superset
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Generate a new package or visualization plugin in `@superset-ui`
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd superset-ui/packages
|
||||||
|
mkdir superset-ui-new-package
|
||||||
|
cd superset-ui-new-package
|
||||||
|
yo @superset-ui/superset
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Apache-2.0
|
||||||
|
|
||||||
|
[learn more about Yeoman](http://yeoman.io/).
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* eslint-disable sort-keys */
|
||||||
|
|
||||||
|
const Generator = require('yeoman-generator');
|
||||||
|
const chalk = require('chalk');
|
||||||
|
const yosay = require('yosay');
|
||||||
|
|
||||||
|
module.exports = class extends Generator {
|
||||||
|
async prompting() {
|
||||||
|
// Have Yeoman greet the user.
|
||||||
|
this.log(
|
||||||
|
yosay(`Welcome to the rad ${chalk.red('generator-superset')} generator!`),
|
||||||
|
);
|
||||||
|
|
||||||
|
this.option('skipInstall');
|
||||||
|
|
||||||
|
this.answers = await this.prompt([
|
||||||
|
{
|
||||||
|
type: 'list',
|
||||||
|
name: 'subgenerator',
|
||||||
|
message: 'What do you want to do?',
|
||||||
|
choices: [
|
||||||
|
{
|
||||||
|
name: 'Create superset-ui core package',
|
||||||
|
value: 'package',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Create superset-ui chart plugin package',
|
||||||
|
value: 'plugin-chart',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
configuring() {
|
||||||
|
// Redirect the default 'app' generator
|
||||||
|
// to 'package' subgenerator
|
||||||
|
// until there are multiple subgenerators
|
||||||
|
// then this can be changed into a menu to select
|
||||||
|
// subgenerator.
|
||||||
|
this.composeWith(require.resolve(`../${this.answers.subgenerator}`));
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* eslint-disable sort-keys */
|
||||||
|
|
||||||
|
const Generator = require('yeoman-generator');
|
||||||
|
const _ = require('lodash');
|
||||||
|
|
||||||
|
module.exports = class extends Generator {
|
||||||
|
async prompting() {
|
||||||
|
this.option('skipInstall');
|
||||||
|
|
||||||
|
this.answers = await this.prompt([
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
name: 'name',
|
||||||
|
message: 'Package name:',
|
||||||
|
default: _.kebabCase(this.appname.replace('superset ui', '').trim()), // Default to current folder name
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'list',
|
||||||
|
name: 'language',
|
||||||
|
message: 'Choose language',
|
||||||
|
default: 'typescript',
|
||||||
|
choices: [
|
||||||
|
{
|
||||||
|
name: 'typescript',
|
||||||
|
value: 'typescript',
|
||||||
|
short: 't',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'javascript',
|
||||||
|
value: 'javascript',
|
||||||
|
short: 'j',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
writing() {
|
||||||
|
this.fs.copyTpl(
|
||||||
|
this.templatePath('_package.json'),
|
||||||
|
this.destinationPath('package.json'),
|
||||||
|
this.answers,
|
||||||
|
);
|
||||||
|
this.fs.copyTpl(
|
||||||
|
this.templatePath('README.md'),
|
||||||
|
this.destinationPath('README.md'),
|
||||||
|
this.answers,
|
||||||
|
);
|
||||||
|
const ext = this.answers.language === 'typescript' ? 'ts' : 'js';
|
||||||
|
this.fs.copy(
|
||||||
|
this.templatePath('src/index.txt'),
|
||||||
|
this.destinationPath(`src/index.${ext}`),
|
||||||
|
);
|
||||||
|
this.fs.copy(
|
||||||
|
this.templatePath('test/index.txt'),
|
||||||
|
this.destinationPath(`test/index.test.${ext}`),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,46 @@
|
||||||
|
<!--
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
or more contributor license agreements. See the NOTICE file
|
||||||
|
distributed with this work for additional information
|
||||||
|
regarding copyright ownership. The ASF licenses this file
|
||||||
|
to you under the Apache License, Version 2.0 (the
|
||||||
|
"License"); you may not use this file except in compliance
|
||||||
|
with the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing,
|
||||||
|
software distributed under the License is distributed on an
|
||||||
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
KIND, either express or implied. See the License for the
|
||||||
|
specific language governing permissions and limitations
|
||||||
|
under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
## @superset-ui/<%= name %>
|
||||||
|
|
||||||
|
[![Version](https://img.shields.io/npm/v/@superset-ui/<%= name
|
||||||
|
%>.svg?style=flat)](https://img.shields.io/npm/v/@superset-ui/<%= name %>.svg?style=flat)
|
||||||
|
[![David (path)](https://img.shields.io/david/apache-superset/superset-ui.svg?path=packages%2Fsuperset-ui-<%=
|
||||||
|
name
|
||||||
|
%>&style=flat-square)](https://david-dm.org/apache-superset/superset-ui?path=packages/superset-ui-<%=
|
||||||
|
name %>)
|
||||||
|
|
||||||
|
Description
|
||||||
|
|
||||||
|
#### Example usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { xxx } from '@superset-ui/<%= name %>';
|
||||||
|
```
|
||||||
|
|
||||||
|
#### API
|
||||||
|
|
||||||
|
`fn(args)`
|
||||||
|
|
||||||
|
- Do something
|
||||||
|
|
||||||
|
### Development
|
||||||
|
|
||||||
|
`@data-ui/build-config` is used to manage the build configuration for this package including babel
|
||||||
|
builds, jest testing, eslint, and prettier.
|
|
@ -0,0 +1,23 @@
|
||||||
|
{
|
||||||
|
"name": "@superset-ui/<%= name %>",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"description": "Superset UI <%= name %>",
|
||||||
|
"sideEffects": false,
|
||||||
|
"main": "lib/index.js",
|
||||||
|
"module": "esm/index.js",
|
||||||
|
"files": ["esm", "lib"],
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/apache-superset/superset-ui.git"
|
||||||
|
},
|
||||||
|
"keywords": ["superset"],
|
||||||
|
"author": "Superset",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/apache-superset/superset-ui/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/apache-superset/superset-ui#readme",
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
const x = 1;
|
||||||
|
export default x;
|
|
@ -0,0 +1,5 @@
|
||||||
|
describe('My Test', () => {
|
||||||
|
it('tests something', () => {
|
||||||
|
expect(1).toEqual(1);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,127 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* eslint-disable sort-keys */
|
||||||
|
|
||||||
|
const Generator = require('yeoman-generator');
|
||||||
|
const _ = require('lodash');
|
||||||
|
|
||||||
|
module.exports = class extends Generator {
|
||||||
|
async prompting() {
|
||||||
|
this.option('skipInstall');
|
||||||
|
|
||||||
|
this.answers = await this.prompt([
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
name: 'packageName',
|
||||||
|
message: 'Package name:',
|
||||||
|
// Default to current folder name
|
||||||
|
default: _.kebabCase(this.appname.replace('plugin chart', '').trim()),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
name: 'description',
|
||||||
|
message: 'Description:',
|
||||||
|
// Default to current folder name
|
||||||
|
default: _.upperFirst(
|
||||||
|
_.startCase(this.appname.replace('plugin chart', '').trim()),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'list',
|
||||||
|
name: 'componentType',
|
||||||
|
message: 'What type of React component would you like?',
|
||||||
|
choices: [
|
||||||
|
{
|
||||||
|
name: 'Class component',
|
||||||
|
value: 'class',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Function component (with hooks)',
|
||||||
|
value: 'function',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'list',
|
||||||
|
name: 'chartType',
|
||||||
|
message: 'What type of chart would you like?',
|
||||||
|
choices: [
|
||||||
|
{
|
||||||
|
name: 'Time-series chart',
|
||||||
|
value: 'timeseries',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Regular chart',
|
||||||
|
value: 'regular',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'confirm',
|
||||||
|
name: 'addBadges',
|
||||||
|
message: "Add superset-ui badges to your plugin's README.md",
|
||||||
|
default: true,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
writing() {
|
||||||
|
// 'hello-world' -> 'HelloWorld'
|
||||||
|
const packageLabel = _.upperFirst(_.camelCase(this.answers.packageName));
|
||||||
|
|
||||||
|
// 'hello-world' -> 'Hello World'
|
||||||
|
const pluginName = _.startCase(_.camelCase(this.answers.packageName));
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
...this.answers,
|
||||||
|
packageLabel,
|
||||||
|
pluginName,
|
||||||
|
};
|
||||||
|
|
||||||
|
[
|
||||||
|
['package.erb', 'package.json'],
|
||||||
|
['tsconfig.json', 'tsconfig.json'],
|
||||||
|
['README.erb', 'README.md'],
|
||||||
|
['src/index.erb', 'src/index.ts'],
|
||||||
|
['src/plugin/buildQuery.erb', 'src/plugin/buildQuery.ts'],
|
||||||
|
['src/plugin/controlPanel.erb', 'src/plugin/controlPanel.ts'],
|
||||||
|
['src/plugin/index.erb', 'src/plugin/index.ts'],
|
||||||
|
['src/plugin/transformProps.erb', 'src/plugin/transformProps.ts'],
|
||||||
|
['src/types.erb', 'src/types.ts'],
|
||||||
|
['src/MyChart.erb', `src/${packageLabel}.tsx`],
|
||||||
|
['test/index.erb', 'test/index.test.ts'],
|
||||||
|
['test/plugin/buildQuery.test.erb', 'test/plugin/buildQuery.test.ts'],
|
||||||
|
[
|
||||||
|
'test/plugin/transformProps.test.erb',
|
||||||
|
'test/plugin/transformProps.test.ts',
|
||||||
|
],
|
||||||
|
].forEach(([src, dest]) => {
|
||||||
|
this.fs.copyTpl(
|
||||||
|
this.templatePath(src),
|
||||||
|
this.destinationPath(dest),
|
||||||
|
params,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
['types/external.d.ts', 'src/images/thumbnail.png'].forEach(file => {
|
||||||
|
this.fs.copy(this.templatePath(file), this.destinationPath(file));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
|
@ -0,0 +1,54 @@
|
||||||
|
## @superset-ui/plugin-chart-<%= packageName %>
|
||||||
|
|
||||||
|
<%if (addBadges) { %>[![Version](https://img.shields.io/npm/v/@superset-ui/plugin-chart-<%= packageName %>.svg?style=flat-square)](https://www.npmjs.com/package/@superset-ui/plugin-chart-<%= packageName %>)<% } %>
|
||||||
|
|
||||||
|
This plugin provides <%= description %> for Superset.
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
Configure `key`, which can be any `string`, and register the plugin. This `key` will be used to lookup this chart throughout the app.
|
||||||
|
|
||||||
|
```js
|
||||||
|
import <%= packageLabel %>ChartPlugin from '@superset-ui/plugin-chart-<%= packageName %>';
|
||||||
|
|
||||||
|
new <%= packageLabel %>ChartPlugin()
|
||||||
|
.configure({ key: '<%= packageName %>' })
|
||||||
|
.register();
|
||||||
|
```
|
||||||
|
|
||||||
|
Then use it via `SuperChart`. See [storybook](https://apache-superset.github.io/superset-ui/?selectedKind=plugin-chart-<%= packageName %>) for more details.
|
||||||
|
|
||||||
|
```js
|
||||||
|
<SuperChart
|
||||||
|
chartType="<%= packageName %>"
|
||||||
|
width={600}
|
||||||
|
height={600}
|
||||||
|
formData={...}
|
||||||
|
queriesData={[{
|
||||||
|
data: {...},
|
||||||
|
}]}
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
### File structure generated
|
||||||
|
|
||||||
|
```
|
||||||
|
├── package.json
|
||||||
|
├── README.md
|
||||||
|
├── tsconfig.json
|
||||||
|
├── src
|
||||||
|
│ ├── <%= packageLabel %>.tsx
|
||||||
|
│ ├── images
|
||||||
|
│ │ └── thumbnail.png
|
||||||
|
│ ├── index.ts
|
||||||
|
│ ├── plugin
|
||||||
|
│ │ ├── buildQuery.ts
|
||||||
|
│ │ ├── controlPanel.ts
|
||||||
|
│ │ ├── index.ts
|
||||||
|
│ │ └── transformProps.ts
|
||||||
|
│ └── types.ts
|
||||||
|
├── test
|
||||||
|
│ └── index.test.ts
|
||||||
|
└── types
|
||||||
|
└── external.d.ts
|
||||||
|
```
|
|
@ -0,0 +1,39 @@
|
||||||
|
{
|
||||||
|
"name": "@superset-ui/plugin-chart-<%= packageName %>",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"description": "Superset Chart - <%= description %>",
|
||||||
|
"sideEffects": false,
|
||||||
|
"main": "lib/index.js",
|
||||||
|
"module": "esm/index.js",
|
||||||
|
"files": [
|
||||||
|
"esm",
|
||||||
|
"lib"
|
||||||
|
],
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/apache-superset/superset-ui.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"superset"
|
||||||
|
],
|
||||||
|
"author": "Superset",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/apache-superset/superset-ui/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/apache-superset/superset-ui#readme",
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@superset-ui/core": "^0.17.40",
|
||||||
|
"@superset-ui/chart-controls": "^0.17.41"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.13.1"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/jest": "^26.0.0",
|
||||||
|
"jest": "^26.0.1"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,113 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import React, { <%if (componentType == 'class') { %>PureComponent<% } %><%if (componentType == 'function') { %>useEffect<% } %>, createRef } from 'react';
|
||||||
|
import { styled } from '@superset-ui/core';
|
||||||
|
import { <%= packageLabel %>Props, <%= packageLabel %>StylesProps } from './types';
|
||||||
|
|
||||||
|
// The following Styles component is a <div> element, which has been styled using Emotion
|
||||||
|
// For docs, visit https://emotion.sh/docs/styled
|
||||||
|
|
||||||
|
// Theming variables are provided for your use via a ThemeProvider
|
||||||
|
// imported from @superset-ui/core. For variables available, please visit
|
||||||
|
// https://github.com/apache-superset/superset-ui/blob/master/packages/superset-ui-core/src/style/index.ts
|
||||||
|
|
||||||
|
const Styles = styled.div<<%= packageLabel %>StylesProps>`
|
||||||
|
background-color: ${({ theme }) => theme.colors.secondary.light2};
|
||||||
|
padding: ${({ theme }) => theme.gridUnit * 4}px;
|
||||||
|
border-radius: ${({ theme }) => theme.gridUnit * 2}px;
|
||||||
|
height: ${({ height }) => height};
|
||||||
|
width: ${({ width }) => width};
|
||||||
|
overflow-y: scroll;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
/* You can use your props to control CSS! */
|
||||||
|
font-size: ${({ theme, headerFontSize }) => theme.typography.sizes[headerFontSize]};
|
||||||
|
font-weight: ${({ theme, boldText }) => theme.typography.weights[boldText ? 'bold' : 'normal']};
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ******************* WHAT YOU CAN BUILD HERE *******************
|
||||||
|
* In essence, a chart is given a few key ingredients to work with:
|
||||||
|
* * Data: provided via `props.data`
|
||||||
|
* * A DOM element
|
||||||
|
* * FormData (your controls!) provided as props by transformProps.ts
|
||||||
|
*/
|
||||||
|
|
||||||
|
<%if (componentType == 'class') { %>export default class <%= packageLabel %> extends PureComponent<<%= packageLabel %>Props> {
|
||||||
|
// Often, you just want to get a hold of the DOM and go nuts.
|
||||||
|
// Here, you can do that with createRef, and componentDidMount.
|
||||||
|
|
||||||
|
rootElem = createRef<HTMLDivElement>();
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
const root = this.rootElem.current as HTMLElement;
|
||||||
|
console.log('Plugin element', root);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
// height and width are the height and width of the DOM element as it exists in the dashboard.
|
||||||
|
// There is also a `data` prop, which is, of course, your DATA 🎉
|
||||||
|
console.log('Approach 1 props', this.props);
|
||||||
|
const { data, height, width } = this.props;
|
||||||
|
|
||||||
|
console.log('Plugin props', this.props);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Styles
|
||||||
|
ref={this.rootElem}
|
||||||
|
boldText={this.props.boldText}
|
||||||
|
headerFontSize={this.props.headerFontSize}
|
||||||
|
height={height}
|
||||||
|
width={width}
|
||||||
|
>
|
||||||
|
<h3>{this.props.headerText}</h3>
|
||||||
|
<pre>{JSON.stringify(data, null, 2)}</pre>
|
||||||
|
</Styles>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}<% } %><%if (componentType == 'function') { %>export default function <%= packageLabel %>(props: <%= packageLabel %>Props) {
|
||||||
|
// height and width are the height and width of the DOM element as it exists in the dashboard.
|
||||||
|
// There is also a `data` prop, which is, of course, your DATA 🎉
|
||||||
|
const { data, height, width } = props;
|
||||||
|
|
||||||
|
const rootElem = createRef<HTMLDivElement>();
|
||||||
|
|
||||||
|
// Often, you just want to get a hold of the DOM and go nuts.
|
||||||
|
// Here, you can do that with createRef, and the useEffect hook.
|
||||||
|
useEffect(() => {
|
||||||
|
const root = rootElem.current as HTMLElement;
|
||||||
|
console.log('Plugin element', root);
|
||||||
|
});
|
||||||
|
|
||||||
|
console.log('Plugin props', props);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Styles
|
||||||
|
ref={rootElem}
|
||||||
|
boldText={props.boldText}
|
||||||
|
headerFontSize={props.headerFontSize}
|
||||||
|
height={height}
|
||||||
|
width={width}
|
||||||
|
>
|
||||||
|
<h3>{props.headerText}</h3>
|
||||||
|
<pre>${JSON.stringify(data, null, 2)}</pre>
|
||||||
|
</Styles>
|
||||||
|
);
|
||||||
|
}<% } %>
|
Binary file not shown.
After Width: | Height: | Size: 5.5 KiB |
|
@ -0,0 +1,27 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
// eslint-disable-next-line import/prefer-default-export
|
||||||
|
export { default as <%= packageLabel %>ChartPlugin } from './plugin';
|
||||||
|
/**
|
||||||
|
* Note: this file exports the default export from <%= packageLabel %>.tsx.
|
||||||
|
* If you want to export multiple visualization modules, you will need to
|
||||||
|
* either add additional plugin folders (similar in structure to ./plugin)
|
||||||
|
* OR export multiple instances of `ChartPlugin` extensions in ./plugin/index.ts
|
||||||
|
* which in turn load exports from <%= packageLabel %>.tsx
|
||||||
|
*/
|
|
@ -0,0 +1,44 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import { buildQueryContext, QueryFormData } from '@superset-ui/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The buildQuery function is used to create an instance of QueryContext that's
|
||||||
|
* sent to the chart data endpoint. In addition to containing information of which
|
||||||
|
* datasource to use, it specifies the type (e.g. full payload, samples, query) and
|
||||||
|
* format (e.g. CSV or JSON) of the result and whether or not to force refresh the data from
|
||||||
|
* the datasource as opposed to using a cached copy of the data, if available.
|
||||||
|
*
|
||||||
|
* More importantly though, QueryContext contains a property `queries`, which is an array of
|
||||||
|
* QueryObjects specifying individual data requests to be made. A QueryObject specifies which
|
||||||
|
* columns, metrics and filters, among others, to use during the query. Usually it will be enough
|
||||||
|
* to specify just one query based on the baseQueryObject, but for some more advanced use cases
|
||||||
|
* it is possible to define post processing operations in the QueryObject, or multiple queries
|
||||||
|
* if a viz needs multiple different result sets.
|
||||||
|
*/
|
||||||
|
export default function buildQuery(formData: QueryFormData) {
|
||||||
|
const { cols: groupby } = formData;
|
||||||
|
return buildQueryContext(formData, baseQueryObject => [
|
||||||
|
{
|
||||||
|
...baseQueryObject,
|
||||||
|
groupby,<%if (chartType === 'timeseries') { %>
|
||||||
|
is_timeseries: true,<% } %>
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
}
|
|
@ -0,0 +1,190 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import { t, validateNonEmpty } from '@superset-ui/core';
|
||||||
|
import { ControlPanelConfig, sections, sharedControls } from '@superset-ui/chart-controls';
|
||||||
|
|
||||||
|
const config: ControlPanelConfig = {
|
||||||
|
/**
|
||||||
|
* The control panel is split into two tabs: "Query" and
|
||||||
|
* "Chart Options". The controls that define the inputs to
|
||||||
|
* the chart data request, such as columns and metrics, usually
|
||||||
|
* reside within "Query", while controls that affect the visual
|
||||||
|
* appearance or functionality of the chart are under the
|
||||||
|
* "Chart Options" section.
|
||||||
|
*
|
||||||
|
* There are several predefined controls that can be used.
|
||||||
|
* Some examples:
|
||||||
|
* - groupby: columns to group by (tranlated to GROUP BY statement)
|
||||||
|
* - series: same as groupby, but single selection.
|
||||||
|
* - metrics: multiple metrics (translated to aggregate expression)
|
||||||
|
* - metric: sane as metrics, but single selection
|
||||||
|
* - adhoc_filters: filters (translated to WHERE or HAVING
|
||||||
|
* depending on filter type)
|
||||||
|
* - row_limit: maximum number of rows (translated to LIMIT statement)
|
||||||
|
*
|
||||||
|
* If a control panel has both a `series` and `groupby` control, and
|
||||||
|
* the user has chosen `col1` as the value for the `series` control,
|
||||||
|
* and `col2` and `col3` as values for the `groupby` control,
|
||||||
|
* the resulting query will contain three `groupby` columns. This is because
|
||||||
|
* we considered `series` control a `groupby` query field and its value
|
||||||
|
* will automatically append the `groupby` field when the query is generated.
|
||||||
|
*
|
||||||
|
* It is also possible to define custom controls by importing the
|
||||||
|
* necessary dependencies and overriding the default parameters, which
|
||||||
|
* can then be placed in the `controlSetRows` section
|
||||||
|
* of the `Query` section instead of a predefined control.
|
||||||
|
*
|
||||||
|
* import { validateNonEmpty } from '@superset-ui/core';
|
||||||
|
* import {
|
||||||
|
* sharedControls,
|
||||||
|
* ControlConfig,
|
||||||
|
* ControlPanelConfig,
|
||||||
|
* } from '@superset-ui/chart-controls';
|
||||||
|
*
|
||||||
|
* const myControl: ControlConfig<'SelectControl'> = {
|
||||||
|
* name: 'secondary_entity',
|
||||||
|
* config: {
|
||||||
|
* ...sharedControls.entity,
|
||||||
|
* type: 'SelectControl',
|
||||||
|
* label: t('Secondary Entity'),
|
||||||
|
* mapStateToProps: state => ({
|
||||||
|
* sharedControls.columnChoices(state.datasource)
|
||||||
|
* .columns.filter(c => c.groupby)
|
||||||
|
* })
|
||||||
|
* validators: [validateNonEmpty],
|
||||||
|
* },
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* In addition to the basic drop down control, there are several predefined
|
||||||
|
* control types (can be set via the `type` property) that can be used. Some
|
||||||
|
* commonly used examples:
|
||||||
|
* - SelectControl: Dropdown to select single or multiple values,
|
||||||
|
usually columns
|
||||||
|
* - MetricsControl: Dropdown to select metrics, triggering a modal
|
||||||
|
to define Metric details
|
||||||
|
* - AdhocFilterControl: Control to choose filters
|
||||||
|
* - CheckboxControl: A checkbox for choosing true/false values
|
||||||
|
* - SliderControl: A slider with min/max values
|
||||||
|
* - TextControl: Control for text data
|
||||||
|
*
|
||||||
|
* For more control input types, check out the `incubator-superset` repo
|
||||||
|
* and open this file: superset-frontend/src/explore/components/controls/index.js
|
||||||
|
*
|
||||||
|
* To ensure all controls have been filled out correctly, the following
|
||||||
|
* validators are provided
|
||||||
|
* by the `@superset-ui/core/lib/validator`:
|
||||||
|
* - validateNonEmpty: must have at least one value
|
||||||
|
* - validateInteger: must be an integer value
|
||||||
|
* - validateNumber: must be an intger or decimal value
|
||||||
|
*/
|
||||||
|
|
||||||
|
// For control input types, see: superset-frontend/src/explore/components/controls/index.js
|
||||||
|
controlPanelSections: [
|
||||||
|
<%if (chartType === 'timeseries') { %>sections.legacyTimeseriesTime,<% } else { %>sections.legacyRegularTime,<% } %>
|
||||||
|
{
|
||||||
|
label: t('Query'),
|
||||||
|
expanded: true,
|
||||||
|
controlSetRows: [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
name: 'cols',
|
||||||
|
config: {
|
||||||
|
...sharedControls.groupby,
|
||||||
|
label: t('Columns'),
|
||||||
|
description: t('Columns to group by'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
name: 'metrics',
|
||||||
|
config: {
|
||||||
|
...sharedControls.metrics,
|
||||||
|
// it's possible to add validators to controls if
|
||||||
|
// certain selections/types need to be enforced
|
||||||
|
validators: [validateNonEmpty],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
['adhoc_filters'],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
name: 'row_limit',
|
||||||
|
config: sharedControls.row_limit,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: t('Hello Controls!'),
|
||||||
|
expanded: true,
|
||||||
|
controlSetRows: [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
name: 'header_text',
|
||||||
|
config: {
|
||||||
|
type: 'TextControl',
|
||||||
|
default: 'Hello, World!',
|
||||||
|
renderTrigger: true,
|
||||||
|
// ^ this makes it apply instantaneously, without triggering a "run query" button
|
||||||
|
label: t('Header Text'),
|
||||||
|
description: t('The text you want to see in the header'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
name: 'bold_text',
|
||||||
|
config: {
|
||||||
|
type: 'CheckboxControl',
|
||||||
|
label: t('Bold Text'),
|
||||||
|
renderTrigger: true,
|
||||||
|
default: true,
|
||||||
|
description: t('A checkbox to make the '),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{
|
||||||
|
name: 'header_font_size',
|
||||||
|
config: {
|
||||||
|
type: 'SelectControl',
|
||||||
|
label: t('Font Size'),
|
||||||
|
default: 'xl',
|
||||||
|
choices: [
|
||||||
|
// [value, label]
|
||||||
|
['xxs', 'xx-small'],
|
||||||
|
['xs', 'x-small'],
|
||||||
|
['s', 'small'],
|
||||||
|
['m', 'medium'],
|
||||||
|
['l', 'large'],
|
||||||
|
['xl', 'x-large'],
|
||||||
|
['xxl', 'xx-large'],
|
||||||
|
],
|
||||||
|
renderTrigger: true,
|
||||||
|
description: t('The size of your header font'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
export default config;
|
|
@ -0,0 +1,51 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import { t, ChartMetadata, ChartPlugin } from '@superset-ui/core';
|
||||||
|
import buildQuery from './buildQuery';
|
||||||
|
import controlPanel from './controlPanel';
|
||||||
|
import transformProps from './transformProps';
|
||||||
|
import thumbnail from '../images/thumbnail.png';
|
||||||
|
|
||||||
|
export default class <%= packageLabel %>ChartPlugin extends ChartPlugin {
|
||||||
|
/**
|
||||||
|
* The constructor is used to pass relevant metadata and callbacks that get
|
||||||
|
* registered in respective registries that are used throughout the library
|
||||||
|
* and application. A more thorough description of each property is given in
|
||||||
|
* the respective imported file.
|
||||||
|
*
|
||||||
|
* It is worth noting that `buildQuery` and is optional, and only needed for
|
||||||
|
* advanced visualizations that require either post processing operations
|
||||||
|
* (pivoting, rolling aggregations, sorting etc) or submitting multiple queries.
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
const metadata = new ChartMetadata({
|
||||||
|
description: '<%= description %>',
|
||||||
|
name: t('<%= pluginName %>'),
|
||||||
|
thumbnail,
|
||||||
|
});
|
||||||
|
|
||||||
|
super({
|
||||||
|
buildQuery,
|
||||||
|
controlPanel,
|
||||||
|
loadChart: () => import('../<%= packageLabel %>'),
|
||||||
|
metadata,
|
||||||
|
transformProps,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import { ChartProps, TimeseriesDataRecord } from '@superset-ui/core';
|
||||||
|
|
||||||
|
export default function transformProps(chartProps: ChartProps) {
|
||||||
|
/**
|
||||||
|
* This function is called after a successful response has been
|
||||||
|
* received from the chart data endpoint, and is used to transform
|
||||||
|
* the incoming data prior to being sent to the Visualization.
|
||||||
|
*
|
||||||
|
* The transformProps function is also quite useful to return
|
||||||
|
* additional/modified props to your data viz component. The formData
|
||||||
|
* can also be accessed from your <%= packageLabel %>.tsx file, but
|
||||||
|
* doing supplying custom props here is often handy for integrating third
|
||||||
|
* party libraries that rely on specific props.
|
||||||
|
*
|
||||||
|
* A description of properties in `chartProps`:
|
||||||
|
* - `height`, `width`: the height/width of the DOM element in which
|
||||||
|
* the chart is located
|
||||||
|
* - `formData`: the chart data request payload that was sent to the
|
||||||
|
* backend.
|
||||||
|
* - `queriesData`: the chart data response payload that was received
|
||||||
|
* from the backend. Some notable properties of `queriesData`:
|
||||||
|
* - `data`: an array with data, each row with an object mapping
|
||||||
|
* the column/alias to its value. Example:
|
||||||
|
* `[{ col1: 'abc', metric1: 10 }, { col1: 'xyz', metric1: 20 }]`
|
||||||
|
* - `rowcount`: the number of rows in `data`
|
||||||
|
* - `query`: the query that was issued.
|
||||||
|
*
|
||||||
|
* Please note: the transformProps function gets cached when the
|
||||||
|
* application loads. When making changes to the `transformProps`
|
||||||
|
* function during development with hot reloading, changes won't
|
||||||
|
* be seen until restarting the development server.
|
||||||
|
*/
|
||||||
|
const { width, height, formData, queriesData } = chartProps;
|
||||||
|
const { boldText, headerFontSize, headerText } = formData;
|
||||||
|
const data = queriesData[0].data as TimeseriesDataRecord[];
|
||||||
|
|
||||||
|
console.log('formData via TransformProps.ts', formData);
|
||||||
|
|
||||||
|
return {
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
<%if (chartType === 'timeseries') { %>
|
||||||
|
data: data.map(item => ({
|
||||||
|
...item,
|
||||||
|
// convert epoch to native Date
|
||||||
|
// eslint-disable-next-line no-underscore-dangle
|
||||||
|
__timestamp: new Date(item.__timestamp as number),
|
||||||
|
})),<% } else { %> data,<% } %>
|
||||||
|
// and now your control data, manipulated as needed, and passed through as props!
|
||||||
|
boldText,
|
||||||
|
headerFontSize,
|
||||||
|
headerText,
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import { QueryFormData, supersetTheme, TimeseriesDataRecord } from '@superset-ui/core';
|
||||||
|
|
||||||
|
export interface <%= packageLabel %>StylesProps {
|
||||||
|
height: number;
|
||||||
|
width: number;
|
||||||
|
headerFontSize: keyof typeof supersetTheme.typography.sizes;
|
||||||
|
boldText: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface <%= packageLabel %>CustomizeProps {
|
||||||
|
headerText: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type <%= packageLabel %>QueryFormData = QueryFormData &
|
||||||
|
<%= packageLabel %>StylesProps &
|
||||||
|
<%= packageLabel %>CustomizeProps;
|
||||||
|
|
||||||
|
export type <%= packageLabel %>Props = <%= packageLabel %>StylesProps &
|
||||||
|
<%= packageLabel %>CustomizeProps & {
|
||||||
|
data: TimeseriesDataRecord[];
|
||||||
|
// add typing here for the props you pass in from transformProps.ts!
|
||||||
|
};
|
|
@ -0,0 +1,33 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import { <%= packageLabel %>ChartPlugin } from '../src';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The example tests in this file act as a starting point, and
|
||||||
|
* we encourage you to build more. These tests check that the
|
||||||
|
* plugin loads properly, and focus on `transformProps`
|
||||||
|
* to ake sure that data, controls, and props are all
|
||||||
|
* treated correctly (e.g. formData from plugin controls
|
||||||
|
* properly transform the data and/or any resulting props).
|
||||||
|
*/
|
||||||
|
describe('@superset-ui/plugin-chart-<%= packageName %>', () => {
|
||||||
|
it('exists', () => {
|
||||||
|
expect(<%= packageLabel %>ChartPlugin).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,34 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import buildQuery from '../../src/plugin/buildQuery';
|
||||||
|
|
||||||
|
describe('<%= packageLabel %> buildQuery', () => {
|
||||||
|
const formData = {
|
||||||
|
datasource: '5__table',
|
||||||
|
granularity_sqla: 'ds',
|
||||||
|
series: 'foo',
|
||||||
|
viz_type: 'my_chart',
|
||||||
|
};
|
||||||
|
|
||||||
|
it('should build groupby with series in form data', () => {
|
||||||
|
const queryContext = buildQuery(formData);
|
||||||
|
const [query] = queryContext.queries;
|
||||||
|
expect(query.groupby).toEqual(['foo']);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,52 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import { ChartProps } from '@superset-ui/core';
|
||||||
|
import transformProps from '../../src/plugin/transformProps';
|
||||||
|
|
||||||
|
describe('<%= packageLabel %> tranformProps', () => {
|
||||||
|
const formData = {
|
||||||
|
colorScheme: 'bnbColors',
|
||||||
|
datasource: '3__table',
|
||||||
|
granularity_sqla: 'ds',
|
||||||
|
metric: 'sum__num',
|
||||||
|
series: 'name',
|
||||||
|
boldText: true,
|
||||||
|
headerFontSize: 'xs',
|
||||||
|
headerText: 'my text',
|
||||||
|
};
|
||||||
|
const chartProps = new ChartProps({
|
||||||
|
formData,
|
||||||
|
width: 800,
|
||||||
|
height: 600,
|
||||||
|
queriesData: [{
|
||||||
|
data: [{ name: 'Hulk', sum__num: 1<%if (chartType === 'timeseries') { %>, __timestamp: 599616000000<% } %> }],
|
||||||
|
}],
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should tranform chart props for viz', () => {
|
||||||
|
expect(transformProps(chartProps)).toEqual({
|
||||||
|
width: 800,
|
||||||
|
height: 600,
|
||||||
|
boldText: true,
|
||||||
|
headerFontSize: 'xs',
|
||||||
|
headerText: 'my text',
|
||||||
|
data: [{ name: 'Hulk', sum__num: 1<%if (chartType === 'timeseries') { %>, __timestamp: new Date(599616000000)<% } %> }],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"declarationDir": "lib",
|
||||||
|
"outDir": "lib",
|
||||||
|
"rootDir": "src"
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"lib",
|
||||||
|
"test"
|
||||||
|
],
|
||||||
|
"extends": "../../tsconfig.json",
|
||||||
|
"include": [
|
||||||
|
"src/**/*",
|
||||||
|
"types/**/*",
|
||||||
|
"../../types/**/*"
|
||||||
|
],
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"path": "../../packages/superset-ui-chart-controls"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "../../packages/superset-ui-core"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare module '*.png' {
|
||||||
|
const value: any;
|
||||||
|
export default value;
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
"name": "@superset-ui/generator-superset",
|
||||||
|
"version": "0.18.25",
|
||||||
|
"description": "Scaffolder for Superset",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/apache-superset/superset-ui/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/apache-superset/superset-ui#readme",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/apache-superset/superset-ui.git"
|
||||||
|
},
|
||||||
|
"author": "Superset",
|
||||||
|
"files": [
|
||||||
|
"generators"
|
||||||
|
],
|
||||||
|
"main": "generators/index.js",
|
||||||
|
"keywords": [
|
||||||
|
"yeoman",
|
||||||
|
"generator",
|
||||||
|
"superset",
|
||||||
|
"yeoman-generator"
|
||||||
|
],
|
||||||
|
"devDependencies": {
|
||||||
|
"yeoman-assert": "^3.1.0",
|
||||||
|
"yeoman-test": "^2.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"npm": ">= 4.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"chalk": "^4.0.0",
|
||||||
|
"lodash": "^4.17.11",
|
||||||
|
"yeoman-generator": "^4.0.0",
|
||||||
|
"yosay": "^2.0.2"
|
||||||
|
},
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,59 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const path = require('path');
|
||||||
|
const assert = require('yeoman-assert');
|
||||||
|
const helpers = require('yeoman-test');
|
||||||
|
|
||||||
|
describe('generator-superset:app', () => {
|
||||||
|
let dir;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
dir = process.cwd();
|
||||||
|
|
||||||
|
return helpers.run(path.join(__dirname, '../generators/app')).withPrompts({
|
||||||
|
subgenerator: 'package',
|
||||||
|
name: 'my-package',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Change working directory back to original working directory
|
||||||
|
* after the test has completed.
|
||||||
|
* yeoman tests switch to tmp directory and write files there.
|
||||||
|
* Usually this is fine for solo package.
|
||||||
|
* However, for a monorepo like this one,
|
||||||
|
* it made jest confuses with current directory
|
||||||
|
* (being in tmp directory instead of superset-ui root)
|
||||||
|
* and interferes with other tests in sibling packages
|
||||||
|
* that are run after the yeoman tests.
|
||||||
|
*/
|
||||||
|
afterAll(() => {
|
||||||
|
process.chdir(dir);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates files', () => {
|
||||||
|
assert.file([
|
||||||
|
'package.json',
|
||||||
|
'README.md',
|
||||||
|
'src/index.ts',
|
||||||
|
'test/index.test.ts',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
const path = require('path');
|
||||||
|
const assert = require('yeoman-assert');
|
||||||
|
const helpers = require('yeoman-test');
|
||||||
|
|
||||||
|
describe('generator-superset:package', () => {
|
||||||
|
let dir;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
dir = process.cwd();
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Change working directory back to original working directory
|
||||||
|
* after the test has completed.
|
||||||
|
* yeoman tests switch to tmp directory and write files there.
|
||||||
|
* Usually this is fine for solo package.
|
||||||
|
* However, for a monorepo like this one,
|
||||||
|
* it made jest confuses with current directory
|
||||||
|
* (being in tmp directory instead of superset-ui root)
|
||||||
|
* and interferes with other tests in sibling packages
|
||||||
|
* that are run after the yeoman tests.
|
||||||
|
*/
|
||||||
|
afterAll(() => {
|
||||||
|
process.chdir(dir);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('typescript', () => {
|
||||||
|
beforeAll(() =>
|
||||||
|
helpers
|
||||||
|
.run(path.join(__dirname, '../generators/package'))
|
||||||
|
.withPrompts({ name: 'my-package', language: 'typescript' })
|
||||||
|
.withOptions({ skipInstall: true }),
|
||||||
|
);
|
||||||
|
|
||||||
|
it('creates files', () => {
|
||||||
|
assert.file([
|
||||||
|
'package.json',
|
||||||
|
'README.md',
|
||||||
|
'src/index.ts',
|
||||||
|
'test/index.test.ts',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('javascript', () => {
|
||||||
|
beforeAll(() =>
|
||||||
|
helpers
|
||||||
|
.run(path.join(__dirname, '../generators/package'))
|
||||||
|
.withPrompts({ name: 'my-package', language: 'javascript' })
|
||||||
|
.withOptions({ skipInstall: true }),
|
||||||
|
);
|
||||||
|
|
||||||
|
it('creates files', () => {
|
||||||
|
assert.file([
|
||||||
|
'package.json',
|
||||||
|
'README.md',
|
||||||
|
'src/index.js',
|
||||||
|
'test/index.test.js',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* eslint-env node */
|
||||||
|
const path = require('path');
|
||||||
|
const assert = require('yeoman-assert');
|
||||||
|
const helpers = require('yeoman-test');
|
||||||
|
|
||||||
|
describe('generator-superset:plugin-chart', () => {
|
||||||
|
let dir;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
dir = process.cwd();
|
||||||
|
|
||||||
|
return helpers
|
||||||
|
.run(path.join(__dirname, '../generators/plugin-chart'))
|
||||||
|
.withPrompts({ packageName: 'cold-map', description: 'Cold Map' })
|
||||||
|
.withOptions({ skipInstall: true });
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Change working directory back to original working directory
|
||||||
|
* after the test has completed.
|
||||||
|
* yeoman tests switch to tmp directory and write files there.
|
||||||
|
* Usually this is fine for solo package.
|
||||||
|
* However, for a monorepo like this one,
|
||||||
|
* it made jest confuses with current directory
|
||||||
|
* (being in tmp directory instead of superset-ui root)
|
||||||
|
* and interferes with other tests in sibling packages
|
||||||
|
* that are run after the yeoman tests.
|
||||||
|
*/
|
||||||
|
afterAll(() => {
|
||||||
|
process.chdir(dir);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates files', () => {
|
||||||
|
assert.file([
|
||||||
|
'package.json',
|
||||||
|
'README.md',
|
||||||
|
'src/plugin/buildQuery.ts',
|
||||||
|
'src/plugin/controlPanel.ts',
|
||||||
|
'src/plugin/index.ts',
|
||||||
|
'src/plugin/transformProps.ts',
|
||||||
|
'src/ColdMap.tsx',
|
||||||
|
'src/index.ts',
|
||||||
|
'test/index.test.ts',
|
||||||
|
'test/plugin/buildQuery.test.ts',
|
||||||
|
'test/plugin/transformProps.test.ts',
|
||||||
|
'types/external.d.ts',
|
||||||
|
'src/images/thumbnail.png',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": false,
|
||||||
|
"emitDeclarationOnly": false,
|
||||||
|
"noEmit": true,
|
||||||
|
"rootDir": "."
|
||||||
|
},
|
||||||
|
"extends": "../../../tsconfig.json",
|
||||||
|
"include": [
|
||||||
|
"**/*",
|
||||||
|
"../types/**/*",
|
||||||
|
"../../../types/**/*"
|
||||||
|
],
|
||||||
|
"references": [
|
||||||
|
{
|
||||||
|
"path": ".."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
<!--
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
or more contributor license agreements. See the NOTICE file
|
||||||
|
distributed with this work for additional information
|
||||||
|
regarding copyright ownership. The ASF licenses this file
|
||||||
|
to you under the Apache License, Version 2.0 (the
|
||||||
|
"License"); you may not use this file except in compliance
|
||||||
|
with the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing,
|
||||||
|
software distributed under the License is distributed on an
|
||||||
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
KIND, either express or implied. See the License for the
|
||||||
|
specific language governing permissions and limitations
|
||||||
|
under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
# Change Log
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
# [0.18.0](https://github.com/apache-superset/superset-ui/compare/v0.17.87...v0.18.0) (2021-08-30)
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* add certified icon to columoption ([#1330](https://github.com/apache-superset/superset-ui/issues/1330)) ([a415c41](https://github.com/apache-superset/superset-ui/commit/a415c413954bc9c093ab5dfde62d458cf3224073))
|
|
@ -0,0 +1,42 @@
|
||||||
|
<!--
|
||||||
|
Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
or more contributor license agreements. See the NOTICE file
|
||||||
|
distributed with this work for additional information
|
||||||
|
regarding copyright ownership. The ASF licenses this file
|
||||||
|
to you under the Apache License, Version 2.0 (the
|
||||||
|
"License"); you may not use this file except in compliance
|
||||||
|
with the License. You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing,
|
||||||
|
software distributed under the License is distributed on an
|
||||||
|
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
KIND, either express or implied. See the License for the
|
||||||
|
specific language governing permissions and limitations
|
||||||
|
under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
## @superset-ui/chart-controls
|
||||||
|
|
||||||
|
[![Version](https://img.shields.io/npm/v/@superset-ui/chart-controls.svg?style=flat)](https://www.npmjs.com/package/@superset-ui/chart-controls)
|
||||||
|
[![David (path)](https://img.shields.io/david/apache-superset/superset-ui.svg?path=packages%2Fsuperset-ui-chart-controls&style=flat-square)](https://david-dm.org/apache-superset/superset-ui?path=packages/superset-ui-chart-controls)
|
||||||
|
|
||||||
|
Description
|
||||||
|
|
||||||
|
#### Example usage
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { xxx } from '@superset-ui/chart-controls';
|
||||||
|
```
|
||||||
|
|
||||||
|
#### API
|
||||||
|
|
||||||
|
`fn(args)`
|
||||||
|
|
||||||
|
- Do something
|
||||||
|
|
||||||
|
### Development
|
||||||
|
|
||||||
|
`@data-ui/build-config` is used to manage the build configuration for this package including babel
|
||||||
|
builds, jest testing, eslint, and prettier.
|
|
@ -0,0 +1,41 @@
|
||||||
|
{
|
||||||
|
"name": "@superset-ui/chart-controls",
|
||||||
|
"version": "0.18.25",
|
||||||
|
"description": "Superset UI control-utils",
|
||||||
|
"sideEffects": false,
|
||||||
|
"main": "lib/index.js",
|
||||||
|
"module": "esm/index.js",
|
||||||
|
"files": [
|
||||||
|
"esm",
|
||||||
|
"lib"
|
||||||
|
],
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/apache-superset/superset-ui.git"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"superset"
|
||||||
|
],
|
||||||
|
"author": "Superset",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/apache-superset/superset-ui/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/apache-superset/superset-ui#readme",
|
||||||
|
"publishConfig": {
|
||||||
|
"access": "public"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@react-icons/all-files": "^4.1.0",
|
||||||
|
"@superset-ui/core": "0.18.25",
|
||||||
|
"lodash": "^4.17.15",
|
||||||
|
"prop-types": "^15.7.2"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@emotion/react": "^11.4.1",
|
||||||
|
"@types/react": "*",
|
||||||
|
"antd": "^4.9.4",
|
||||||
|
"react": "^16.13.1",
|
||||||
|
"react-dom": "^16.13.1"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import React from 'react';
|
||||||
|
import { kebabCase } from 'lodash';
|
||||||
|
import { t, useTheme, styled } from '@superset-ui/core';
|
||||||
|
import Tooltip from './Tooltip';
|
||||||
|
|
||||||
|
interface CertifiedIconWithTooltipProps {
|
||||||
|
certifiedBy?: string | null;
|
||||||
|
details?: string | null;
|
||||||
|
metricName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const StyledDiv = styled.div`
|
||||||
|
margin-bottom: ${({ theme }) => theme.gridUnit * 2}px;
|
||||||
|
`;
|
||||||
|
|
||||||
|
function CertifiedIconWithTooltip({
|
||||||
|
certifiedBy,
|
||||||
|
details,
|
||||||
|
metricName,
|
||||||
|
}: CertifiedIconWithTooltipProps) {
|
||||||
|
const theme = useTheme();
|
||||||
|
return (
|
||||||
|
<Tooltip
|
||||||
|
id={`${kebabCase(metricName)}-tooltip`}
|
||||||
|
title={
|
||||||
|
<div>
|
||||||
|
{certifiedBy && (
|
||||||
|
<StyledDiv>{t('Certified by %s', certifiedBy)}</StyledDiv>
|
||||||
|
)}
|
||||||
|
<div>{details}</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{/* TODO: move Icons to superset-ui to remove duplicated icon code here */}
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
enableBackground="new 0 0 24 24"
|
||||||
|
height="16"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="16"
|
||||||
|
>
|
||||||
|
<g>
|
||||||
|
<path
|
||||||
|
fill={theme.colors.primary.base}
|
||||||
|
d="M23,12l-2.44-2.79l0.34-3.69l-3.61-0.82L15.4,1.5L12,2.96L8.6,1.5L6.71,4.69L3.1,5.5L3.44,9.2L1,12l2.44,2.79l-0.34,3.7 l3.61,0.82L8.6,22.5l3.4-1.47l3.4,1.46l1.89-3.19l3.61-0.82l-0.34-3.69L23,12z M9.38,16.01L7,13.61c-0.39-0.39-0.39-1.02,0-1.41 l0.07-0.07c0.39-0.39,1.03-0.39,1.42,0l1.61,1.62l5.15-5.16c0.39-0.39,1.03-0.39,1.42,0l0.07,0.07c0.39,0.39,0.39,1.02,0,1.41 l-5.92,5.94C10.41,16.4,9.78,16.4,9.38,16.01z"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CertifiedIconWithTooltip;
|
|
@ -0,0 +1,101 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import React from 'react';
|
||||||
|
import { styled } from '@superset-ui/core';
|
||||||
|
import { Tooltip } from './Tooltip';
|
||||||
|
import { ColumnTypeLabel } from './ColumnTypeLabel';
|
||||||
|
import InfoTooltipWithTrigger from './InfoTooltipWithTrigger';
|
||||||
|
import CertifiedIconWithTooltip from './CertifiedIconWithTooltip';
|
||||||
|
import { ColumnMeta } from '../types';
|
||||||
|
|
||||||
|
export type ColumnOptionProps = {
|
||||||
|
column: ColumnMeta;
|
||||||
|
showType?: boolean;
|
||||||
|
showTooltip?: boolean;
|
||||||
|
labelRef?: React.RefObject<any>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const StyleOverrides = styled.span`
|
||||||
|
svg {
|
||||||
|
margin-right: ${({ theme }) => theme.gridUnit}px;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export function ColumnOption({
|
||||||
|
column,
|
||||||
|
labelRef,
|
||||||
|
showType = false,
|
||||||
|
showTooltip = true,
|
||||||
|
}: ColumnOptionProps) {
|
||||||
|
const { expression, column_name, type_generic } = column;
|
||||||
|
const hasExpression = expression && expression !== column_name;
|
||||||
|
const type = hasExpression ? 'expression' : type_generic;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<StyleOverrides>
|
||||||
|
{showType && type !== undefined && <ColumnTypeLabel type={type} />}
|
||||||
|
{column.is_certified && (
|
||||||
|
<CertifiedIconWithTooltip
|
||||||
|
metricName={column.metric_name}
|
||||||
|
certifiedBy={column.certified_by}
|
||||||
|
details={column.certification_details}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{showTooltip ? (
|
||||||
|
<Tooltip
|
||||||
|
id="metric-name-tooltip"
|
||||||
|
title={column.verbose_name || column.column_name}
|
||||||
|
trigger={['hover']}
|
||||||
|
placement="top"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className="m-r-5 option-label column-option-label"
|
||||||
|
ref={labelRef}
|
||||||
|
>
|
||||||
|
{column.verbose_name || column.column_name}
|
||||||
|
</span>
|
||||||
|
</Tooltip>
|
||||||
|
) : (
|
||||||
|
<span className="m-r-5 option-label column-option-label" ref={labelRef}>
|
||||||
|
{column.verbose_name || column.column_name}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{column.description && (
|
||||||
|
<InfoTooltipWithTrigger
|
||||||
|
className="m-r-5 text-muted"
|
||||||
|
icon="info"
|
||||||
|
tooltip={column.description}
|
||||||
|
label={`descr-${column.column_name}`}
|
||||||
|
placement="top"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{hasExpression && (
|
||||||
|
<InfoTooltipWithTrigger
|
||||||
|
className="m-r-5 text-muted"
|
||||||
|
icon="question-circle-o"
|
||||||
|
tooltip={column.expression}
|
||||||
|
label={`expr-${column.column_name}`}
|
||||||
|
placement="top"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</StyleOverrides>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ColumnOption;
|
|
@ -0,0 +1,58 @@
|
||||||
|
/* eslint-disable no-nested-ternary */
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import { GenericDataType } from '@superset-ui/core';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
type StringIcon = '?' | 'ƒ' | 'AGG' | 'ABC' | '#' | 'T/F' | 'time';
|
||||||
|
|
||||||
|
export type ColumnLabelExtendedType = 'expression' | 'aggregate' | '';
|
||||||
|
|
||||||
|
export type ColumnTypeLabelProps = {
|
||||||
|
type?: ColumnLabelExtendedType | GenericDataType;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function ColumnTypeLabel({ type }: ColumnTypeLabelProps) {
|
||||||
|
let stringIcon: StringIcon = '?';
|
||||||
|
|
||||||
|
if (type === '' || type === 'expression') {
|
||||||
|
stringIcon = 'ƒ';
|
||||||
|
} else if (type === 'aggregate') {
|
||||||
|
stringIcon = 'AGG';
|
||||||
|
} else if (type === GenericDataType.STRING) {
|
||||||
|
stringIcon = 'ABC';
|
||||||
|
} else if (type === GenericDataType.NUMERIC) {
|
||||||
|
stringIcon = '#';
|
||||||
|
} else if (type === GenericDataType.BOOLEAN) {
|
||||||
|
stringIcon = 'T/F';
|
||||||
|
} else if (type === GenericDataType.TEMPORAL) {
|
||||||
|
stringIcon = 'time';
|
||||||
|
}
|
||||||
|
|
||||||
|
const typeIcon =
|
||||||
|
stringIcon === 'time' ? (
|
||||||
|
<i className="fa fa-clock-o type-label" />
|
||||||
|
) : (
|
||||||
|
<div className="type-label">{stringIcon}</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
return <span>{typeIcon}</span>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ColumnTypeLabel;
|
|
@ -0,0 +1,124 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import React, { useState, FunctionComponentElement, ChangeEvent } from 'react';
|
||||||
|
import { JsonValue, useTheme } from '@superset-ui/core';
|
||||||
|
import ControlHeader, { ControlHeaderProps } from '../ControlHeader';
|
||||||
|
import InfoTooltipWithTrigger from '../InfoTooltipWithTrigger';
|
||||||
|
import { ControlFormItemComponents, ControlFormItemSpec } from './controls';
|
||||||
|
|
||||||
|
export * from './controls';
|
||||||
|
|
||||||
|
export type ControlFormItemProps = ControlFormItemSpec & {
|
||||||
|
name: string;
|
||||||
|
onChange?: (fieldValue: JsonValue) => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ControlFormItemNode =
|
||||||
|
FunctionComponentElement<ControlFormItemProps>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accept `false` or `0`, but not empty string.
|
||||||
|
*/
|
||||||
|
function isEmptyValue(value?: JsonValue) {
|
||||||
|
return value == null || value === '';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ControlFormItem({
|
||||||
|
name,
|
||||||
|
label,
|
||||||
|
description,
|
||||||
|
width,
|
||||||
|
validators,
|
||||||
|
required,
|
||||||
|
onChange,
|
||||||
|
value: initialValue,
|
||||||
|
defaultValue,
|
||||||
|
controlType,
|
||||||
|
...props
|
||||||
|
}: ControlFormItemProps) {
|
||||||
|
const { gridUnit } = useTheme();
|
||||||
|
const [hovered, setHovered] = useState(false);
|
||||||
|
const [value, setValue] = useState(
|
||||||
|
initialValue === undefined ? defaultValue : initialValue,
|
||||||
|
);
|
||||||
|
const [validationErrors, setValidationErrors] =
|
||||||
|
useState<ControlHeaderProps['validationErrors']>();
|
||||||
|
|
||||||
|
const handleChange = (e: ChangeEvent<HTMLInputElement> | JsonValue) => {
|
||||||
|
const fieldValue =
|
||||||
|
e && typeof e === 'object' && 'target' in e
|
||||||
|
? e.target.type === 'checkbox' || e.target.type === 'radio'
|
||||||
|
? e.target.checked
|
||||||
|
: e.target.value
|
||||||
|
: e;
|
||||||
|
const errors =
|
||||||
|
(validators
|
||||||
|
?.map(validator =>
|
||||||
|
!required && isEmptyValue(fieldValue) ? false : validator(fieldValue),
|
||||||
|
)
|
||||||
|
.filter(x => !!x) as string[]) || [];
|
||||||
|
setValidationErrors(errors);
|
||||||
|
setValue(fieldValue);
|
||||||
|
if (errors.length === 0 && onChange) {
|
||||||
|
onChange(fieldValue as JsonValue);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const Control = ControlFormItemComponents[controlType];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
css={{
|
||||||
|
margin: 2 * gridUnit,
|
||||||
|
width,
|
||||||
|
}}
|
||||||
|
onMouseEnter={() => setHovered(true)}
|
||||||
|
onMouseLeave={() => setHovered(false)}
|
||||||
|
>
|
||||||
|
{controlType === 'Checkbox' ? (
|
||||||
|
<ControlFormItemComponents.Checkbox
|
||||||
|
checked={value as boolean}
|
||||||
|
onChange={handleChange}
|
||||||
|
>
|
||||||
|
{label}{' '}
|
||||||
|
{hovered && description && (
|
||||||
|
<InfoTooltipWithTrigger tooltip={description} />
|
||||||
|
)}
|
||||||
|
</ControlFormItemComponents.Checkbox>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{label && (
|
||||||
|
<ControlHeader
|
||||||
|
name={name}
|
||||||
|
label={label}
|
||||||
|
description={description}
|
||||||
|
validationErrors={validationErrors}
|
||||||
|
hovered={hovered}
|
||||||
|
required={required}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{/* @ts-ignore */}
|
||||||
|
<Control {...props} value={value} onChange={handleChange} />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ControlFormItem;
|
|
@ -0,0 +1,92 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import React, { ReactNode } from 'react';
|
||||||
|
import { Slider, InputNumber, Input } from 'antd';
|
||||||
|
import Checkbox, { CheckboxProps } from 'antd/lib/checkbox';
|
||||||
|
import Select, { SelectOption } from '../Select';
|
||||||
|
import RadioButtonControl, {
|
||||||
|
RadioButtonOption,
|
||||||
|
} from '../../shared-controls/components/RadioButtonControl';
|
||||||
|
|
||||||
|
export const ControlFormItemComponents = {
|
||||||
|
Slider,
|
||||||
|
InputNumber,
|
||||||
|
Input,
|
||||||
|
Select,
|
||||||
|
// Directly export Checkbox will result in "using name from external module" error
|
||||||
|
// ref: https://stackoverflow.com/questions/43900035/ts4023-exported-variable-x-has-or-is-using-name-y-from-external-module-but
|
||||||
|
Checkbox: Checkbox as React.ForwardRefExoticComponent<
|
||||||
|
CheckboxProps & React.RefAttributes<HTMLInputElement>
|
||||||
|
>,
|
||||||
|
RadioButtonControl,
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ControlType = keyof typeof ControlFormItemComponents;
|
||||||
|
|
||||||
|
export type ControlFormValueValidator<V> = (value: V) => string | false;
|
||||||
|
|
||||||
|
export type ControlFormItemSpec<T extends ControlType = ControlType> = {
|
||||||
|
controlType: T;
|
||||||
|
label: ReactNode;
|
||||||
|
description: ReactNode;
|
||||||
|
placeholder?: string;
|
||||||
|
required?: boolean;
|
||||||
|
validators?: ControlFormValueValidator<any>[];
|
||||||
|
width?: number | string;
|
||||||
|
/**
|
||||||
|
* Time to delay change propagation.
|
||||||
|
*/
|
||||||
|
debounceDelay?: number;
|
||||||
|
} & (T extends 'Select'
|
||||||
|
? {
|
||||||
|
options: SelectOption<any>[];
|
||||||
|
value?: string;
|
||||||
|
defaultValue?: string;
|
||||||
|
creatable?: boolean;
|
||||||
|
minWidth?: number | string;
|
||||||
|
validators?: ControlFormValueValidator<string>[];
|
||||||
|
}
|
||||||
|
: T extends 'RadioButtonControl'
|
||||||
|
? {
|
||||||
|
options: RadioButtonOption[];
|
||||||
|
value?: string;
|
||||||
|
defaultValue?: string;
|
||||||
|
}
|
||||||
|
: T extends 'Checkbox'
|
||||||
|
? {
|
||||||
|
value?: boolean;
|
||||||
|
defaultValue?: boolean;
|
||||||
|
}
|
||||||
|
: T extends 'InputNumber' | 'Slider'
|
||||||
|
? {
|
||||||
|
min?: number;
|
||||||
|
max?: number;
|
||||||
|
step?: number;
|
||||||
|
value?: number;
|
||||||
|
defaultValue?: number;
|
||||||
|
validators?: ControlFormValueValidator<number>[];
|
||||||
|
}
|
||||||
|
: T extends 'Input'
|
||||||
|
? {
|
||||||
|
controlType: 'Input';
|
||||||
|
value?: string;
|
||||||
|
defaultValue?: string;
|
||||||
|
validators?: ControlFormValueValidator<string>[];
|
||||||
|
}
|
||||||
|
: {});
|
|
@ -0,0 +1,135 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import React, { FunctionComponentElement, useMemo } from 'react';
|
||||||
|
import {
|
||||||
|
FAST_DEBOUNCE,
|
||||||
|
JsonObject,
|
||||||
|
JsonValue,
|
||||||
|
useTheme,
|
||||||
|
} from '@superset-ui/core';
|
||||||
|
import { debounce } from 'lodash';
|
||||||
|
import { ControlFormItemNode } from './ControlFormItem';
|
||||||
|
|
||||||
|
export * from './ControlFormItem';
|
||||||
|
|
||||||
|
export type ControlFormRowProps = {
|
||||||
|
children: ControlFormItemNode | ControlFormItemNode[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export function ControlFormRow({ children }: ControlFormRowProps) {
|
||||||
|
const { gridUnit } = useTheme();
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
css={{
|
||||||
|
display: 'flex',
|
||||||
|
flexWrap: 'nowrap',
|
||||||
|
margin: -2 * gridUnit,
|
||||||
|
marginBottom: gridUnit,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
type ControlFormRowNode = FunctionComponentElement<ControlFormRowProps>;
|
||||||
|
|
||||||
|
export type ControlFormProps = {
|
||||||
|
/**
|
||||||
|
* Form field values dict.
|
||||||
|
*/
|
||||||
|
value?: JsonObject;
|
||||||
|
onChange: (value: JsonObject) => void;
|
||||||
|
children: ControlFormRowNode | ControlFormRowNode[];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Light weight form for control panel.
|
||||||
|
*/
|
||||||
|
export default function ControlForm({
|
||||||
|
onChange,
|
||||||
|
value,
|
||||||
|
children,
|
||||||
|
}: ControlFormProps) {
|
||||||
|
const theme = useTheme();
|
||||||
|
const debouncedOnChange = useMemo(
|
||||||
|
() =>
|
||||||
|
({
|
||||||
|
0: onChange,
|
||||||
|
[FAST_DEBOUNCE]: debounce(onChange, FAST_DEBOUNCE),
|
||||||
|
} as Record<number, typeof onChange>),
|
||||||
|
[onChange],
|
||||||
|
);
|
||||||
|
|
||||||
|
const updatedChildren = React.Children.map(children, row => {
|
||||||
|
if ('children' in row.props) {
|
||||||
|
const defaultWidth = Array.isArray(row.props.children)
|
||||||
|
? `${100 / row.props.children.length}%`
|
||||||
|
: undefined;
|
||||||
|
return React.cloneElement(row, {
|
||||||
|
children: React.Children.map(row.props.children, item => {
|
||||||
|
const {
|
||||||
|
name,
|
||||||
|
width,
|
||||||
|
debounceDelay = FAST_DEBOUNCE,
|
||||||
|
onChange: onItemValueChange,
|
||||||
|
} = item.props;
|
||||||
|
return React.cloneElement(item, {
|
||||||
|
width: width || defaultWidth,
|
||||||
|
value: value?.[name],
|
||||||
|
// remove `debounceDelay` from rendered control item props
|
||||||
|
// so React DevTools don't throw a `invalid prop` warning.
|
||||||
|
debounceDelay: undefined,
|
||||||
|
onChange(fieldValue: JsonValue) {
|
||||||
|
// call `onChange` on each FormItem
|
||||||
|
if (onItemValueChange) {
|
||||||
|
onItemValueChange(fieldValue);
|
||||||
|
}
|
||||||
|
// propagate to the form
|
||||||
|
if (!(debounceDelay in debouncedOnChange)) {
|
||||||
|
debouncedOnChange[debounceDelay] = debounce(
|
||||||
|
onChange,
|
||||||
|
debounceDelay,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
debouncedOnChange[debounceDelay]({
|
||||||
|
...value,
|
||||||
|
[name]: fieldValue,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return row;
|
||||||
|
});
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
css={{
|
||||||
|
label: {
|
||||||
|
textTransform: 'uppercase',
|
||||||
|
color: theme.colors.text.label,
|
||||||
|
fontSize: theme.typography.sizes.s,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{updatedChildren}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,142 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import React, { ReactNode } from 'react';
|
||||||
|
import { t } from '@superset-ui/core';
|
||||||
|
import { InfoTooltipWithTrigger } from './InfoTooltipWithTrigger';
|
||||||
|
import { Tooltip } from './Tooltip';
|
||||||
|
|
||||||
|
type ValidationError = string;
|
||||||
|
|
||||||
|
export type ControlHeaderProps = {
|
||||||
|
name?: string;
|
||||||
|
label?: ReactNode;
|
||||||
|
description?: ReactNode;
|
||||||
|
validationErrors?: ValidationError[];
|
||||||
|
renderTrigger?: boolean;
|
||||||
|
rightNode?: ReactNode;
|
||||||
|
leftNode?: ReactNode;
|
||||||
|
hovered?: boolean;
|
||||||
|
required?: boolean;
|
||||||
|
warning?: string;
|
||||||
|
danger?: string;
|
||||||
|
onClick?: () => void;
|
||||||
|
tooltipOnClick?: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function ControlHeader({
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
label,
|
||||||
|
tooltipOnClick,
|
||||||
|
onClick,
|
||||||
|
warning,
|
||||||
|
danger,
|
||||||
|
leftNode,
|
||||||
|
rightNode,
|
||||||
|
validationErrors = [],
|
||||||
|
renderTrigger = false,
|
||||||
|
hovered = false,
|
||||||
|
required = false,
|
||||||
|
}: ControlHeaderProps) {
|
||||||
|
const renderOptionalIcons = () => {
|
||||||
|
if (hovered) {
|
||||||
|
return (
|
||||||
|
<span>
|
||||||
|
{description && (
|
||||||
|
<span>
|
||||||
|
<InfoTooltipWithTrigger
|
||||||
|
label={t('description')}
|
||||||
|
tooltip={description}
|
||||||
|
placement="top"
|
||||||
|
onClick={tooltipOnClick}
|
||||||
|
/>{' '}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{renderTrigger && (
|
||||||
|
<span>
|
||||||
|
<InfoTooltipWithTrigger
|
||||||
|
label={t('bolt')}
|
||||||
|
tooltip={t('Changing this control takes effect instantly')}
|
||||||
|
placement="top"
|
||||||
|
icon="bolt"
|
||||||
|
/>{' '}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!label) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const labelClass = validationErrors.length > 0 ? 'text-danger' : '';
|
||||||
|
return (
|
||||||
|
<div className="ControlHeader" data-test={`${name}-header`}>
|
||||||
|
<div className="pull-left">
|
||||||
|
<label className="control-label" htmlFor={name}>
|
||||||
|
{leftNode && <span>{leftNode}</span>}
|
||||||
|
<span
|
||||||
|
role="button"
|
||||||
|
tabIndex={0}
|
||||||
|
onClick={onClick}
|
||||||
|
className={labelClass}
|
||||||
|
style={{ cursor: onClick ? 'pointer' : '' }}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
</span>{' '}
|
||||||
|
{warning && (
|
||||||
|
<span>
|
||||||
|
<Tooltip id="error-tooltip" placement="top" title={warning}>
|
||||||
|
<i className="fa fa-exclamation-circle text-warning" />
|
||||||
|
</Tooltip>{' '}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{danger && (
|
||||||
|
<span>
|
||||||
|
<Tooltip id="error-tooltip" placement="top" title={danger}>
|
||||||
|
<i className="fa fa-exclamation-circle text-danger" />
|
||||||
|
</Tooltip>{' '}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{validationErrors.length > 0 && (
|
||||||
|
<span>
|
||||||
|
<Tooltip
|
||||||
|
id="error-tooltip"
|
||||||
|
placement="top"
|
||||||
|
title={validationErrors.join(' ')}
|
||||||
|
>
|
||||||
|
<i className="fa fa-exclamation-circle text-danger" />
|
||||||
|
</Tooltip>{' '}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{renderOptionalIcons()}
|
||||||
|
{required && (
|
||||||
|
<span className="text-danger m-l-4">
|
||||||
|
<strong>*</strong>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
{rightNode && <div className="pull-right">{rightNode}</div>}
|
||||||
|
<div className="clearfix" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import React from 'react';
|
||||||
|
import { kebabCase } from 'lodash';
|
||||||
|
import { TooltipPlacement } from 'antd/lib/tooltip';
|
||||||
|
import { t } from '@superset-ui/core';
|
||||||
|
import { Tooltip, TooltipProps } from './Tooltip';
|
||||||
|
|
||||||
|
export interface InfoTooltipWithTriggerProps {
|
||||||
|
label?: string;
|
||||||
|
tooltip?: TooltipProps['title'];
|
||||||
|
icon?: string;
|
||||||
|
onClick?: () => void;
|
||||||
|
placement?: TooltipPlacement;
|
||||||
|
bsStyle?: string;
|
||||||
|
className?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function InfoTooltipWithTrigger({
|
||||||
|
label,
|
||||||
|
tooltip,
|
||||||
|
bsStyle,
|
||||||
|
onClick,
|
||||||
|
icon = 'info-circle',
|
||||||
|
className = 'text-muted',
|
||||||
|
placement = 'right',
|
||||||
|
}: InfoTooltipWithTriggerProps) {
|
||||||
|
const iconClass = `fa fa-${icon} ${className} ${
|
||||||
|
bsStyle ? `text-${bsStyle}` : ''
|
||||||
|
}`;
|
||||||
|
const iconEl = (
|
||||||
|
<i
|
||||||
|
role="button"
|
||||||
|
aria-label={t('Show info tooltip')}
|
||||||
|
tabIndex={0}
|
||||||
|
className={iconClass}
|
||||||
|
style={{ cursor: onClick ? 'pointer' : undefined }}
|
||||||
|
onClick={onClick}
|
||||||
|
onKeyPress={
|
||||||
|
onClick &&
|
||||||
|
(event => {
|
||||||
|
if (event.key === 'Enter' || event.key === ' ') {
|
||||||
|
onClick();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
if (!tooltip) {
|
||||||
|
return iconEl;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Tooltip
|
||||||
|
id={`${kebabCase(label)}-tooltip`}
|
||||||
|
title={tooltip}
|
||||||
|
placement={placement}
|
||||||
|
>
|
||||||
|
{iconEl}
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default InfoTooltipWithTrigger;
|
|
@ -0,0 +1,117 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import React from 'react';
|
||||||
|
import { styled, Metric, SafeMarkdown } from '@superset-ui/core';
|
||||||
|
import InfoTooltipWithTrigger from './InfoTooltipWithTrigger';
|
||||||
|
import { ColumnTypeLabel } from './ColumnTypeLabel';
|
||||||
|
import CertifiedIconWithTooltip from './CertifiedIconWithTooltip';
|
||||||
|
import Tooltip from './Tooltip';
|
||||||
|
|
||||||
|
const FlexRowContainer = styled.div`
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
> svg {
|
||||||
|
margin-right: ${({ theme }) => theme.gridUnit}px;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export interface MetricOptionProps {
|
||||||
|
metric: Omit<Metric, 'id'> & { label?: string };
|
||||||
|
openInNewWindow?: boolean;
|
||||||
|
showFormula?: boolean;
|
||||||
|
showType?: boolean;
|
||||||
|
showTooltip?: boolean;
|
||||||
|
url?: string;
|
||||||
|
labelRef?: React.RefObject<any>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function MetricOption({
|
||||||
|
metric,
|
||||||
|
labelRef,
|
||||||
|
openInNewWindow = false,
|
||||||
|
showFormula = true,
|
||||||
|
showType = false,
|
||||||
|
showTooltip = true,
|
||||||
|
url = '',
|
||||||
|
}: MetricOptionProps) {
|
||||||
|
const verbose = metric.verbose_name || metric.metric_name || metric.label;
|
||||||
|
const link = url ? (
|
||||||
|
<a href={url} target={openInNewWindow ? '_blank' : ''} rel="noreferrer">
|
||||||
|
{verbose}
|
||||||
|
</a>
|
||||||
|
) : (
|
||||||
|
verbose
|
||||||
|
);
|
||||||
|
|
||||||
|
const warningMarkdown = metric.warning_markdown || metric.warning_text;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<FlexRowContainer className="metric-option">
|
||||||
|
{showType && <ColumnTypeLabel type="expression" />}
|
||||||
|
{metric.is_certified && (
|
||||||
|
<CertifiedIconWithTooltip
|
||||||
|
metricName={metric.metric_name}
|
||||||
|
certifiedBy={metric.certified_by}
|
||||||
|
details={metric.certification_details}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{showTooltip ? (
|
||||||
|
<Tooltip
|
||||||
|
id="metric-name-tooltip"
|
||||||
|
title={verbose}
|
||||||
|
trigger={['hover']}
|
||||||
|
placement="top"
|
||||||
|
>
|
||||||
|
<span className="option-label metric-option-label" ref={labelRef}>
|
||||||
|
{link}
|
||||||
|
</span>
|
||||||
|
</Tooltip>
|
||||||
|
) : (
|
||||||
|
<span className="option-label metric-option-label" ref={labelRef}>
|
||||||
|
{link}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{metric.description && (
|
||||||
|
<InfoTooltipWithTrigger
|
||||||
|
className="text-muted"
|
||||||
|
icon="info"
|
||||||
|
tooltip={metric.description}
|
||||||
|
label={`descr-${metric.metric_name}`}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{showFormula && (
|
||||||
|
<InfoTooltipWithTrigger
|
||||||
|
className="text-muted"
|
||||||
|
icon="question-circle-o"
|
||||||
|
tooltip={metric.expression}
|
||||||
|
label={`expr-${metric.metric_name}`}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{warningMarkdown && (
|
||||||
|
<InfoTooltipWithTrigger
|
||||||
|
className="text-warning"
|
||||||
|
icon="warning"
|
||||||
|
tooltip={<SafeMarkdown source={warningMarkdown} />}
|
||||||
|
label={`warn-${metric.metric_name}`}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</FlexRowContainer>
|
||||||
|
);
|
||||||
|
}
|
|
@ -0,0 +1,107 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import React, { useState, ReactNode } from 'react';
|
||||||
|
import AntdSelect, { SelectProps as AntdSelectProps } from 'antd/lib/select';
|
||||||
|
|
||||||
|
export const { Option }: any = AntdSelect;
|
||||||
|
|
||||||
|
export type SelectOption<VT = string> = [VT, ReactNode];
|
||||||
|
|
||||||
|
export type SelectProps<VT> = Omit<AntdSelectProps<VT>, 'options'> & {
|
||||||
|
creatable?: boolean;
|
||||||
|
minWidth?: string | number;
|
||||||
|
options?: SelectOption<VT>[];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AntD select with creatable options.
|
||||||
|
*/
|
||||||
|
export default function Select<VT extends string | number>({
|
||||||
|
creatable,
|
||||||
|
onSearch,
|
||||||
|
dropdownMatchSelectWidth = false,
|
||||||
|
minWidth = '100%',
|
||||||
|
showSearch: showSearch_ = true,
|
||||||
|
onChange,
|
||||||
|
options,
|
||||||
|
children,
|
||||||
|
value,
|
||||||
|
...props
|
||||||
|
}: SelectProps<VT>) {
|
||||||
|
const [searchValue, setSearchValue] = useState<string>();
|
||||||
|
// force show search if creatable
|
||||||
|
const showSearch = showSearch_ || creatable;
|
||||||
|
const handleSearch = showSearch
|
||||||
|
? (input: string) => {
|
||||||
|
if (creatable) {
|
||||||
|
setSearchValue(input);
|
||||||
|
}
|
||||||
|
if (onSearch) {
|
||||||
|
onSearch(input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
const optionsHasSearchValue = options?.some(([val]) => val === searchValue);
|
||||||
|
const optionsHasValue = options?.some(([val]) => val === value);
|
||||||
|
|
||||||
|
const handleChange: SelectProps<VT>['onChange'] = showSearch
|
||||||
|
? (val, opt) => {
|
||||||
|
// reset input value once selected
|
||||||
|
setSearchValue('');
|
||||||
|
if (onChange) {
|
||||||
|
onChange(val, opt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
: onChange;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AntdSelect<VT>
|
||||||
|
dropdownMatchSelectWidth={dropdownMatchSelectWidth}
|
||||||
|
showSearch={showSearch}
|
||||||
|
onSearch={handleSearch}
|
||||||
|
onChange={handleChange}
|
||||||
|
value={value}
|
||||||
|
{...props}
|
||||||
|
css={{
|
||||||
|
minWidth,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{options?.map(([val, label]) => (
|
||||||
|
<Option value={val}>{label}</Option>
|
||||||
|
))}
|
||||||
|
{children}
|
||||||
|
{value && !optionsHasValue && (
|
||||||
|
<Option key={value} value={value}>
|
||||||
|
{value}
|
||||||
|
</Option>
|
||||||
|
)}
|
||||||
|
{searchValue && !optionsHasSearchValue && (
|
||||||
|
<Option key={searchValue} value={searchValue}>
|
||||||
|
{/* Unfortunately AntD select does not support displaying different
|
||||||
|
label for option vs select value, so we can't use
|
||||||
|
`t('Create "%s"', searchValue)` here */}
|
||||||
|
{searchValue}
|
||||||
|
</Option>
|
||||||
|
)}
|
||||||
|
</AntdSelect>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Select.Option = Option;
|
|
@ -0,0 +1,58 @@
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
import { useTheme, css } from '@superset-ui/core';
|
||||||
|
import { Tooltip as BaseTooltip } from 'antd';
|
||||||
|
import { TooltipProps } from 'antd/lib/tooltip';
|
||||||
|
import { Global } from '@emotion/react';
|
||||||
|
|
||||||
|
export { TooltipProps } from 'antd/lib/tooltip';
|
||||||
|
|
||||||
|
export const Tooltip = ({ overlayStyle, color, ...props }: TooltipProps) => {
|
||||||
|
const theme = useTheme();
|
||||||
|
const defaultColor = `${theme.colors.grayscale.dark2}e6`;
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{/* Safari hack to hide browser default tooltips */}
|
||||||
|
<Global
|
||||||
|
styles={css`
|
||||||
|
.ant-tooltip-open {
|
||||||
|
display: inline-block;
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
/>
|
||||||
|
<BaseTooltip
|
||||||
|
overlayStyle={{
|
||||||
|
fontSize: theme.typography.sizes.s,
|
||||||
|
lineHeight: '1.6',
|
||||||
|
...overlayStyle,
|
||||||
|
}}
|
||||||
|
color={defaultColor || color}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Tooltip;
|
|
@ -0,0 +1,47 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import { t, QueryMode, DTTM_ALIAS, GenericDataType } from '@superset-ui/core';
|
||||||
|
import { ColumnMeta } from './types';
|
||||||
|
|
||||||
|
// eslint-disable-next-line import/prefer-default-export
|
||||||
|
export const TIME_FILTER_LABELS = {
|
||||||
|
time_range: t('Time Range'),
|
||||||
|
granularity_sqla: t('Time Column'),
|
||||||
|
time_grain_sqla: t('Time Grain'),
|
||||||
|
druid_time_origin: t('Origin'),
|
||||||
|
granularity: t('Time Granularity'),
|
||||||
|
};
|
||||||
|
|
||||||
|
export const COLUMN_NAME_ALIASES: Record<string, string> = {
|
||||||
|
[DTTM_ALIAS]: t('Time'),
|
||||||
|
};
|
||||||
|
|
||||||
|
export const TIME_COLUMN_OPTION: ColumnMeta = {
|
||||||
|
verbose_name: COLUMN_NAME_ALIASES[DTTM_ALIAS],
|
||||||
|
column_name: DTTM_ALIAS,
|
||||||
|
type_generic: GenericDataType.TEMPORAL,
|
||||||
|
description: t(
|
||||||
|
'A reference to the [Time] configuration, taking granularity into account',
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
export const QueryModeLabel = {
|
||||||
|
[QueryMode.aggregate]: t('Aggregate'),
|
||||||
|
[QueryMode.raw]: t('Raw records'),
|
||||||
|
};
|
|
@ -0,0 +1,43 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import * as sectionsModule from './sections';
|
||||||
|
|
||||||
|
export * from './utils';
|
||||||
|
export * from './constants';
|
||||||
|
export * from './operators';
|
||||||
|
|
||||||
|
// can't do `export * as sections from './sections'`, babel-transformer will fail
|
||||||
|
export const sections = sectionsModule;
|
||||||
|
|
||||||
|
export * from './components/InfoTooltipWithTrigger';
|
||||||
|
export * from './components/ColumnOption';
|
||||||
|
export * from './components/ColumnTypeLabel';
|
||||||
|
export * from './components/MetricOption';
|
||||||
|
|
||||||
|
// React control components
|
||||||
|
export {
|
||||||
|
sharedControls,
|
||||||
|
dndEntity,
|
||||||
|
dndColumnsControl,
|
||||||
|
} from './shared-controls';
|
||||||
|
export { default as sharedControlComponents } from './shared-controls/components';
|
||||||
|
export { legacySortBy } from './shared-controls/legacySortBy';
|
||||||
|
export * from './shared-controls/emitFilterControl';
|
||||||
|
export * from './shared-controls/components';
|
||||||
|
export * from './types';
|
|
@ -0,0 +1,66 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitationsxw
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import {
|
||||||
|
ensureIsArray,
|
||||||
|
getColumnLabel,
|
||||||
|
getMetricLabel,
|
||||||
|
PostProcessingBoxplot,
|
||||||
|
} from '@superset-ui/core';
|
||||||
|
import { PostProcessingFactory } from './types';
|
||||||
|
|
||||||
|
type BoxPlotQueryObjectWhiskerType =
|
||||||
|
PostProcessingBoxplot['options']['whisker_type'];
|
||||||
|
const PERCENTILE_REGEX = /(\d+)\/(\d+) percentiles/;
|
||||||
|
|
||||||
|
export const boxplotOperator: PostProcessingFactory<
|
||||||
|
PostProcessingBoxplot | undefined
|
||||||
|
> = (formData, queryObject) => {
|
||||||
|
const { groupby, whiskerOptions } = formData;
|
||||||
|
|
||||||
|
if (whiskerOptions) {
|
||||||
|
let whiskerType: BoxPlotQueryObjectWhiskerType;
|
||||||
|
let percentiles: [number, number] | undefined;
|
||||||
|
const percentileMatch = PERCENTILE_REGEX.exec(whiskerOptions as string);
|
||||||
|
|
||||||
|
if (whiskerOptions === 'Tukey' || !whiskerOptions) {
|
||||||
|
whiskerType = 'tukey';
|
||||||
|
} else if (whiskerOptions === 'Min/max (no outliers)') {
|
||||||
|
whiskerType = 'min/max';
|
||||||
|
} else if (percentileMatch) {
|
||||||
|
whiskerType = 'percentile';
|
||||||
|
percentiles = [
|
||||||
|
parseInt(percentileMatch[1], 10),
|
||||||
|
parseInt(percentileMatch[2], 10),
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
throw new Error(`Unsupported whisker type: ${whiskerOptions}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
operation: 'boxplot',
|
||||||
|
options: {
|
||||||
|
whisker_type: whiskerType,
|
||||||
|
percentiles,
|
||||||
|
groupby: ensureIsArray(groupby).map(getColumnLabel),
|
||||||
|
metrics: ensureIsArray(queryObject.metrics).map(getMetricLabel),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
|
@ -0,0 +1,34 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitationsxw
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import { PostProcessingContribution } from '@superset-ui/core';
|
||||||
|
import { PostProcessingFactory } from './types';
|
||||||
|
|
||||||
|
export const contributionOperator: PostProcessingFactory<
|
||||||
|
PostProcessingContribution | undefined
|
||||||
|
> = (formData, queryObject) => {
|
||||||
|
if (formData.contributionMode) {
|
||||||
|
return {
|
||||||
|
operation: 'contribution',
|
||||||
|
options: {
|
||||||
|
orientation: formData.contributionMode,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
|
@ -0,0 +1,29 @@
|
||||||
|
/* eslint-disable camelcase */
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitationsxw
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
export { rollingWindowOperator } from './rollingWindowOperator';
|
||||||
|
export { timeCompareOperator } from './timeCompareOperator';
|
||||||
|
export { timeComparePivotOperator } from './timeComparePivotOperator';
|
||||||
|
export { sortOperator } from './sortOperator';
|
||||||
|
export { pivotOperator } from './pivotOperator';
|
||||||
|
export { resampleOperator } from './resampleOperator';
|
||||||
|
export { contributionOperator } from './contributionOperator';
|
||||||
|
export { prophetOperator } from './prophetOperator';
|
||||||
|
export { boxplotOperator } from './boxplotOperator';
|
||||||
|
export * from './utils';
|
|
@ -0,0 +1,54 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitationsxw
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import {
|
||||||
|
ensureIsArray,
|
||||||
|
getColumnLabel,
|
||||||
|
getMetricLabel,
|
||||||
|
PostProcessingPivot,
|
||||||
|
} from '@superset-ui/core';
|
||||||
|
import { PostProcessingFactory } from './types';
|
||||||
|
import { TIME_COLUMN, isValidTimeCompare } from './utils';
|
||||||
|
import { timeComparePivotOperator } from './timeComparePivotOperator';
|
||||||
|
|
||||||
|
export const pivotOperator: PostProcessingFactory<
|
||||||
|
PostProcessingPivot | undefined
|
||||||
|
> = (formData, queryObject) => {
|
||||||
|
const metricLabels = ensureIsArray(queryObject.metrics).map(getMetricLabel);
|
||||||
|
if (queryObject.is_timeseries && metricLabels.length) {
|
||||||
|
if (isValidTimeCompare(formData, queryObject)) {
|
||||||
|
return timeComparePivotOperator(formData, queryObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
operation: 'pivot',
|
||||||
|
options: {
|
||||||
|
index: [TIME_COLUMN],
|
||||||
|
columns: ensureIsArray(queryObject.columns).map(getColumnLabel),
|
||||||
|
// Create 'dummy' mean aggregates to assign cell values in pivot table
|
||||||
|
// use the 'mean' aggregates to avoid drop NaN. PR: https://github.com/apache-superset/superset-ui/pull/1231
|
||||||
|
aggregates: Object.fromEntries(
|
||||||
|
metricLabels.map(metric => [metric, { operator: 'mean' }]),
|
||||||
|
),
|
||||||
|
drop_missing_columns: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
};
|
|
@ -0,0 +1,39 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitationsxw
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import { PostProcessingProphet } from '@superset-ui/core';
|
||||||
|
import { PostProcessingFactory } from './types';
|
||||||
|
|
||||||
|
export const prophetOperator: PostProcessingFactory<
|
||||||
|
PostProcessingProphet | undefined
|
||||||
|
> = (formData, queryObject) => {
|
||||||
|
if (formData.forecastEnabled) {
|
||||||
|
return {
|
||||||
|
operation: 'prophet',
|
||||||
|
options: {
|
||||||
|
time_grain: formData.time_grain_sqla,
|
||||||
|
periods: parseInt(formData.forecastPeriods, 10),
|
||||||
|
confidence_interval: parseFloat(formData.forecastInterval),
|
||||||
|
yearly_seasonality: formData.forecastSeasonalityYearly,
|
||||||
|
weekly_seasonality: formData.forecastSeasonalityWeekly,
|
||||||
|
daily_seasonality: formData.forecastSeasonalityDaily,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
|
@ -0,0 +1,42 @@
|
||||||
|
/* eslint-disable camelcase */
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitationsxw
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import { PostProcessingResample } from '@superset-ui/core';
|
||||||
|
import { PostProcessingFactory } from './types';
|
||||||
|
import { TIME_COLUMN } from './utils';
|
||||||
|
|
||||||
|
export const resampleOperator: PostProcessingFactory<
|
||||||
|
PostProcessingResample | undefined
|
||||||
|
> = (formData, queryObject) => {
|
||||||
|
const resampleZeroFill = formData.resample_method === 'zerofill';
|
||||||
|
const resampleMethod = resampleZeroFill ? 'asfreq' : formData.resample_method;
|
||||||
|
const resampleRule = formData.resample_rule;
|
||||||
|
if (resampleMethod && resampleRule) {
|
||||||
|
return {
|
||||||
|
operation: 'resample',
|
||||||
|
options: {
|
||||||
|
method: resampleMethod,
|
||||||
|
rule: resampleRule,
|
||||||
|
fill_value: resampleZeroFill ? 0 : null,
|
||||||
|
time_column: TIME_COLUMN,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
|
@ -0,0 +1,93 @@
|
||||||
|
/* eslint-disable camelcase */
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitationsxw
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import {
|
||||||
|
ensureIsInt,
|
||||||
|
ensureIsArray,
|
||||||
|
RollingType,
|
||||||
|
PostProcessingRolling,
|
||||||
|
PostProcessingCum,
|
||||||
|
ComparisionType,
|
||||||
|
} from '@superset-ui/core';
|
||||||
|
import {
|
||||||
|
getMetricOffsetsMap,
|
||||||
|
isValidTimeCompare,
|
||||||
|
TIME_COMPARISON_SEPARATOR,
|
||||||
|
} from './utils';
|
||||||
|
import { PostProcessingFactory } from './types';
|
||||||
|
|
||||||
|
export const rollingWindowOperator: PostProcessingFactory<
|
||||||
|
PostProcessingRolling | PostProcessingCum | undefined
|
||||||
|
> = (formData, queryObject) => {
|
||||||
|
let columns: (string | undefined)[];
|
||||||
|
if (isValidTimeCompare(formData, queryObject)) {
|
||||||
|
const metricsMap = getMetricOffsetsMap(formData, queryObject);
|
||||||
|
const comparisonType = formData.comparison_type;
|
||||||
|
if (comparisonType === ComparisionType.Values) {
|
||||||
|
// time compare type: actual values
|
||||||
|
columns = [
|
||||||
|
...Array.from(metricsMap.values()),
|
||||||
|
...Array.from(metricsMap.keys()),
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
// time compare type: difference / percentage / ratio
|
||||||
|
columns = Array.from(metricsMap.entries()).map(([offset, metric]) =>
|
||||||
|
[comparisonType, metric, offset].join(TIME_COMPARISON_SEPARATOR),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
columns = ensureIsArray(queryObject.metrics).map(metric => {
|
||||||
|
if (typeof metric === 'string') {
|
||||||
|
return metric;
|
||||||
|
}
|
||||||
|
return metric.label;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const columnsMap = Object.fromEntries(columns.map(col => [col, col]));
|
||||||
|
|
||||||
|
if (formData.rolling_type === RollingType.Cumsum) {
|
||||||
|
return {
|
||||||
|
operation: 'cum',
|
||||||
|
options: {
|
||||||
|
operator: 'sum',
|
||||||
|
columns: columnsMap,
|
||||||
|
is_pivot_df: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
[RollingType.Sum, RollingType.Mean, RollingType.Std].includes(
|
||||||
|
formData.rolling_type,
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
operation: 'rolling',
|
||||||
|
options: {
|
||||||
|
rolling_type: formData.rolling_type,
|
||||||
|
window: ensureIsInt(formData.rolling_periods, 1),
|
||||||
|
min_periods: ensureIsInt(formData.min_periods, 0),
|
||||||
|
columns: columnsMap,
|
||||||
|
is_pivot_df: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
};
|
|
@ -0,0 +1,41 @@
|
||||||
|
/* eslint-disable camelcase */
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitationsxw
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import { PostProcessingSort, RollingType } from '@superset-ui/core';
|
||||||
|
import { PostProcessingFactory } from './types';
|
||||||
|
import { TIME_COLUMN } from './utils';
|
||||||
|
|
||||||
|
export const sortOperator: PostProcessingFactory<
|
||||||
|
PostProcessingSort | undefined
|
||||||
|
> = (formData, queryObject) => {
|
||||||
|
if (
|
||||||
|
queryObject.is_timeseries &&
|
||||||
|
Object.values(RollingType).includes(formData.rolling_type)
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
operation: 'sort',
|
||||||
|
options: {
|
||||||
|
columns: {
|
||||||
|
[TIME_COLUMN]: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
};
|
|
@ -0,0 +1,46 @@
|
||||||
|
/* eslint-disable camelcase */
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitationsxw
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import { ComparisionType, PostProcessingCompare } from '@superset-ui/core';
|
||||||
|
import { getMetricOffsetsMap, isValidTimeCompare } from './utils';
|
||||||
|
import { PostProcessingFactory } from './types';
|
||||||
|
|
||||||
|
export const timeCompareOperator: PostProcessingFactory<
|
||||||
|
PostProcessingCompare | undefined
|
||||||
|
> = (formData, queryObject) => {
|
||||||
|
const comparisonType = formData.comparison_type;
|
||||||
|
const metricOffsetMap = getMetricOffsetsMap(formData, queryObject);
|
||||||
|
|
||||||
|
if (
|
||||||
|
isValidTimeCompare(formData, queryObject) &&
|
||||||
|
comparisonType !== ComparisionType.Values
|
||||||
|
) {
|
||||||
|
return {
|
||||||
|
operation: 'compare',
|
||||||
|
options: {
|
||||||
|
source_columns: Array.from(metricOffsetMap.values()),
|
||||||
|
compare_columns: Array.from(metricOffsetMap.keys()),
|
||||||
|
compare_type: comparisonType,
|
||||||
|
drop_original_columns: true,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
};
|
|
@ -0,0 +1,70 @@
|
||||||
|
/* eslint-disable camelcase */
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitationsxw
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import {
|
||||||
|
ComparisionType,
|
||||||
|
PostProcessingPivot,
|
||||||
|
NumpyFunction,
|
||||||
|
ensureIsArray,
|
||||||
|
getColumnLabel,
|
||||||
|
} from '@superset-ui/core';
|
||||||
|
import {
|
||||||
|
getMetricOffsetsMap,
|
||||||
|
isValidTimeCompare,
|
||||||
|
TIME_COMPARISON_SEPARATOR,
|
||||||
|
} from './utils';
|
||||||
|
import { PostProcessingFactory } from './types';
|
||||||
|
|
||||||
|
export const timeComparePivotOperator: PostProcessingFactory<
|
||||||
|
PostProcessingPivot | undefined
|
||||||
|
> = (formData, queryObject) => {
|
||||||
|
const comparisonType = formData.comparison_type;
|
||||||
|
const metricOffsetMap = getMetricOffsetsMap(formData, queryObject);
|
||||||
|
|
||||||
|
if (isValidTimeCompare(formData, queryObject)) {
|
||||||
|
const valuesAgg = Object.fromEntries(
|
||||||
|
[...metricOffsetMap.values(), ...metricOffsetMap.keys()].map(metric => [
|
||||||
|
metric,
|
||||||
|
// use the 'mean' aggregates to avoid drop NaN
|
||||||
|
{ operator: 'mean' as NumpyFunction },
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
const changeAgg = Object.fromEntries(
|
||||||
|
[...metricOffsetMap.entries()]
|
||||||
|
.map(([offset, metric]) =>
|
||||||
|
[comparisonType, metric, offset].join(TIME_COMPARISON_SEPARATOR),
|
||||||
|
)
|
||||||
|
// use the 'mean' aggregates to avoid drop NaN
|
||||||
|
.map(metric => [metric, { operator: 'mean' as NumpyFunction }]),
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
operation: 'pivot',
|
||||||
|
options: {
|
||||||
|
index: ['__timestamp'],
|
||||||
|
columns: ensureIsArray(queryObject.columns).map(getColumnLabel),
|
||||||
|
aggregates:
|
||||||
|
comparisonType === ComparisionType.Values ? valuesAgg : changeAgg,
|
||||||
|
drop_missing_columns: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
};
|
|
@ -0,0 +1,23 @@
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitationsxw
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import { QueryFormData, QueryObject } from '@superset-ui/core';
|
||||||
|
|
||||||
|
export interface PostProcessingFactory<T> {
|
||||||
|
(formData: QueryFormData, queryObject: QueryObject): T;
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
/* eslint-disable camelcase */
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitationsxw
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
export const TIME_COMPARISON_SEPARATOR = '__';
|
||||||
|
export const TIME_COLUMN = '__timestamp';
|
|
@ -0,0 +1,50 @@
|
||||||
|
/* eslint-disable camelcase */
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitationsxw
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import { getMetricLabel, ensureIsArray } from '@superset-ui/core';
|
||||||
|
import { PostProcessingFactory } from '../types';
|
||||||
|
import { TIME_COMPARISON_SEPARATOR } from './constants';
|
||||||
|
|
||||||
|
export const getMetricOffsetsMap: PostProcessingFactory<Map<string, string>> = (
|
||||||
|
formData,
|
||||||
|
queryObject,
|
||||||
|
) => {
|
||||||
|
/*
|
||||||
|
return metric offset-label and metric-label hashmap, for instance:
|
||||||
|
{
|
||||||
|
"SUM(value)__1 year ago": "SUM(value)",
|
||||||
|
"SUM(value)__2 year ago": "SUM(value)"
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
const queryMetrics = ensureIsArray(queryObject.metrics);
|
||||||
|
const timeOffsets = ensureIsArray(formData.time_compare);
|
||||||
|
|
||||||
|
const metricLabels = queryMetrics.map(getMetricLabel);
|
||||||
|
const metricOffsetMap = new Map<string, string>();
|
||||||
|
metricLabels.forEach((metric: string) => {
|
||||||
|
timeOffsets.forEach((offset: string) => {
|
||||||
|
metricOffsetMap.set(
|
||||||
|
[metric, offset].join(TIME_COMPARISON_SEPARATOR),
|
||||||
|
metric,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return metricOffsetMap;
|
||||||
|
};
|
|
@ -0,0 +1,22 @@
|
||||||
|
/* eslint-disable camelcase */
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitationsxw
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
export { getMetricOffsetsMap } from './getMetricOffsetsMap';
|
||||||
|
export { isValidTimeCompare } from './isValidTimeCompare';
|
||||||
|
export { TIME_COMPARISON_SEPARATOR, TIME_COLUMN } from './constants';
|
|
@ -0,0 +1,35 @@
|
||||||
|
/* eslint-disable camelcase */
|
||||||
|
/**
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
* or more contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. The ASF licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitationsxw
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
import { ComparisionType } from '@superset-ui/core';
|
||||||
|
import { getMetricOffsetsMap } from './getMetricOffsetsMap';
|
||||||
|
import { PostProcessingFactory } from '../types';
|
||||||
|
|
||||||
|
export const isValidTimeCompare: PostProcessingFactory<boolean> = (
|
||||||
|
formData,
|
||||||
|
queryObject,
|
||||||
|
) => {
|
||||||
|
const comparisonType = formData.comparison_type;
|
||||||
|
const metricOffsetMap = getMetricOffsetsMap(formData, queryObject);
|
||||||
|
|
||||||
|
return (
|
||||||
|
Object.values(ComparisionType).includes(comparisonType) &&
|
||||||
|
metricOffsetMap.size > 0
|
||||||
|
);
|
||||||
|
};
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue