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
|
||||
# limitations under the License.
|
||||
#
|
||||
*.ipynb
|
||||
*.bak
|
||||
*.db
|
||||
*.pyc
|
||||
|
|
|
@ -49,4 +49,5 @@ repos:
|
|||
rev: v2.4.1 # Use the sha or tag you want to point at
|
||||
hooks:
|
||||
- id: prettier
|
||||
args: ['--ignore-path=./superset-frontend/.prettierignore']
|
||||
files: 'superset-frontend'
|
||||
|
|
|
@ -59,5 +59,5 @@ tsconfig.tsbuildinfo
|
|||
.*iml
|
||||
.esprintrc
|
||||
.prettierignore
|
||||
superset-frontend/packages/generator-superset
|
||||
superset-frontend/temporary_superset_ui
|
||||
generator-superset/*
|
||||
temporary_superset_ui/*
|
||||
|
|
|
@ -28,3 +28,4 @@ src/dashboard/deprecated/*
|
|||
src/temp/*
|
||||
**/node_modules
|
||||
*.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',
|
||||
},
|
||||
testEnvironment: 'jsdom',
|
||||
modulePathIgnorePatterns: ['<rootDir>/temporary_superset_ui'],
|
||||
setupFilesAfterEnv: ['<rootDir>/spec/helpers/setup.ts'],
|
||||
testURL: 'http://localhost',
|
||||
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