feat(storybook): Co-habitating/Upgrading Storybooks to v7 (dependency madness ensues) (#26907)

This commit is contained in:
Evan Rusackas 2024-02-15 07:40:17 -07:00 committed by GitHub
parent e43097329f
commit 753ef69529
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
233 changed files with 22456 additions and 23297 deletions

View File

@ -23,3 +23,5 @@ jobs:
# compatible/incompatible licenses addressed here: https://www.apache.org/legal/resolved.html
# find SPDX identifiers here: https://spdx.org/licenses/
deny-licenses: MS-LPL, BUSL-1.1, QPL-1.0, Sleepycat, SSPL-1.0, CPOL-1.02, AGPL-3.0, GPL-1.0+, BSD-4-Clause-UC, NPL-1.0, NPL-1.1, JSON
# adding an exception for an ambigious license on store2, which has been resolved in the latest version. It's MIT: https://github.com/nbubna/store/blob/master/LICENSE-MIT
allow-dependencies-licenses: 'pkg:npm/store2@2.14.2'

1
.gitignore vendored
View File

@ -71,6 +71,7 @@ superset/static/version_info.json
superset-frontend/**/esm/*
superset-frontend/**/lib/*
superset-frontend/**/storybook-static/*
superset-frontend/migration-storybook.log
yarn-error.log
*.map
*.min.js

View File

@ -78,7 +78,7 @@ repos:
- id: black
language_version: python3
- repo: https://github.com/pre-commit/mirrors-prettier
rev: v2.4.1 # Use the sha or tag you want to point at
rev: v3.1.0 # Use the sha or tag you want to point at
hooks:
- id: prettier
args: ["--ignore-path=./superset-frontend/.prettierignore"]

View File

@ -43,6 +43,7 @@ module.exports = {
'prettier/react',
'plugin:react-hooks/recommended',
'plugin:react-prefer-function-component/recommended',
'plugin:storybook/recommended',
],
parser: '@babel/eslint-parser',
parserOptions: {
@ -69,13 +70,13 @@ module.exports = {
},
},
plugins: [
'prettier',
'react',
'file-progress',
'lodash',
'theme-colors',
'translation-vars',
'react-prefer-function-component',
'prettier',
],
overrides: [
{
@ -88,7 +89,7 @@ module.exports = {
'prettier/@typescript-eslint',
'prettier/react',
],
plugins: ['@typescript-eslint/eslint-plugin', 'prettier', 'react'],
plugins: ['@typescript-eslint/eslint-plugin', 'react', 'prettier'],
rules: {
'@typescript-eslint/ban-ts-ignore': 0,
'@typescript-eslint/ban-ts-comment': 0, // disabled temporarily
@ -161,6 +162,28 @@ module.exports = {
'react/static-property-placement': 0, // re-enable up for discussion
'prettier/prettier': 'error',
'file-progress/activate': 1,
// delete me later: temporary rules to help with migration
'jsx-no-useless-fragment': 0,
'react/function-component-definition': [
0,
{
namedComponents: 'arrow-function',
},
],
'default-param-last': 0,
'react/no-unstable-nested-components': 0,
'react/jsx-no-useless-fragment': 0,
'react/no-unknown-property': 0,
'no-restricted-exports': 0,
'react/default-props-match-prop-types': 0,
'no-unsafe-optional-chaining': 0,
'react/state-in-constructor': 0,
'import/no-import-module-exports': 0,
'no-promise-executor-return': 0,
'prefer-regex-literals': 0,
'react/no-unused-class-component-methods': 0,
'import/no-relative-packages': 0,
'prefer-exponentiation-operator': 0,
},
settings: {
'import/resolver': {
@ -203,6 +226,22 @@ module.exports = {
],
'no-only-tests/no-only-tests': 'error',
'max-classes-per-file': 0,
// temporary rules to help with migration - please re-enable!
'testing-library/await-async-queries': 0,
'testing-library/await-async-utils': 0,
'testing-library/no-await-sync-events': 0,
'testing-library/no-render-in-lifecycle': 0,
'testing-library/no-unnecessary-act': 0,
'testing-library/no-wait-for-multiple-assertions': 0,
'testing-library/prefer-screen-queries': 0,
'testing-library/await-async-events': 0,
'testing-library/no-node-access': 0,
'testing-library/no-wait-for-side-effects': 0,
'testing-library/prefer-presence-queries': 0,
'testing-library/render-result-naming-convention': 0,
'testing-library/no-container': 0,
'testing-library/prefer-find-by': 0,
'testing-library/no-manual-cleanup': 0,
},
},
{
@ -222,6 +261,8 @@ module.exports = {
'theme-colors/no-literal-colors': 0,
'translation-vars/no-template-vars': 0,
'no-restricted-imports': 0,
'jest/no-alias-methods': 0,
'react/no-void-elements': 0,
},
},
],
@ -310,6 +351,24 @@ module.exports = {
'react/static-property-placement': 0, // disabled temporarily
'react-prefer-function-component/react-prefer-function-component': 1,
'prettier/prettier': 'error',
// disabling some things that come with the eslint 7->8 upgrade. Will address these in a separate PR
'jest/no-alias-methods': 0,
'react/no-unknown-property': 0,
'react/no-void-elements': 0,
'react/function-component-definition': [
0,
{
namedComponents: 'arrow-function',
},
],
'react/no-unstable-nested-components': 0,
'react/jsx-no-useless-fragment': 0,
'default-param-last': 0,
'no-import-assign': 0,
'import/no-relative-packages': 0,
'default-case-last': 0,
'no-promise-executor-return': 0,
'react/no-unused-class-component-methods': 0,
},
ignorePatterns,
};

View File

@ -1,3 +1,4 @@
import { dirname, join } from 'path';
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@ -20,21 +21,21 @@
const customConfig = require('../webpack.config.js');
module.exports = {
core: {
builder: 'webpack5',
},
stories: [
'../src/@(components|common|filters|explore|views|dashboard|features)/**/*.stories.@(tsx|jsx)',
'../src/@(components|common|filters|explore|views|dashboard|features)/**/*.*.@(mdx)',
'../packages/superset-ui-demo/storybook/stories/**/*.*.@(tsx|jsx)',
],
addons: [
'@storybook/addon-essentials',
'@storybook/addon-links',
'storybook-addon-jsx',
'@storybook/addon-knobs',
'storybook-addon-paddings',
getAbsolutePath('@storybook/addon-essentials'),
getAbsolutePath('@storybook/addon-links'),
getAbsolutePath('storybook-addon-jsx'),
getAbsolutePath('@storybook/addon-controls'),
getAbsolutePath('@storybook/addon-mdx-gfm'),
],
staticDirs: ['../src/assets/images'],
webpackFinal: config => ({
...config,
module: {
@ -47,7 +48,21 @@ module.exports = {
},
plugins: [...config.plugins, ...customConfig.plugins],
}),
typescript: {
reactDocgen: 'react-docgen-typescript',
},
framework: {
name: getAbsolutePath('@storybook/react-webpack5'),
options: {},
},
docs: {
autodocs: false,
},
};
function getAbsolutePath(value) {
return dirname(require.resolve(join(value, 'package.json')));
}

View File

@ -17,10 +17,7 @@
* under the License.
*/
import React from 'react';
import { addDecorator } from '@storybook/react';
import { jsxDecorator } from 'storybook-addon-jsx';
import { addParameters } from '@storybook/react';
import WithPaddings from 'storybook-addon-paddings';
import { supersetTheme, ThemeProvider } from '@superset-ui/core';
import { combineReducers, createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
@ -52,12 +49,9 @@ const providerDecorator = Story => (
</Provider>
);
addDecorator(jsxDecorator);
addDecorator(themeDecorator);
addDecorator(providerDecorator);
addDecorator(WithPaddings);
export const decorators = [jsxDecorator, themeDecorator, providerDecorator];
addParameters({
export const parameters = {
paddings: {
values: [
{ name: 'None', value: '0px' },
@ -88,4 +82,4 @@ addParameters({
},
},
controls: { expanded: true, sort: 'alpha' },
});
};

File diff suppressed because it is too large Load Diff

View File

@ -41,7 +41,7 @@
"build": "cross-env NODE_OPTIONS=--max_old_space_size=8192 NODE_ENV=production BABEL_ENV=\"${BABEL_ENV:=production}\" webpack --mode=production --color",
"build-dev": "cross-env NODE_OPTIONS=--max_old_space_size=8192 NODE_ENV=development webpack --mode=development --color",
"build-instrumented": "cross-env NODE_ENV=production BABEL_ENV=instrumented webpack --mode=production --color",
"build-storybook": "build-storybook",
"build-storybook": "storybook build",
"check-translation": "prettier --check ../superset/translations/**/LC_MESSAGES/*.json",
"chromatic": "npx chromatic --skip 'dependabot/**' --only-changed",
"clean-translation": "prettier --write ../superset/translations/**/LC_MESSAGES/*.json",
@ -52,7 +52,7 @@
"eslint": "eslint --ignore-path=.eslintignore --ext .js,.jsx,.ts,tsx",
"format": "npm run _prettier -- --write",
"lint": "npm run eslint -- . && npm run type",
"lint-fix": "npm run eslint -- . --fix",
"lint-fix": "npm run eslint -- . --fix --quiet",
"lint-stats": "eslint -f ./scripts/eslint-metrics-uploader.js --ignore-path=.eslintignore --ext .js,.jsx,.ts,.tsx . ",
"plugins:build": "node ./scripts/build.js",
"plugins:build-assets": "node ./scripts/copyAssets.js",
@ -68,7 +68,7 @@
"prettier-check": "npm run _prettier -- --check",
"prod": "npm run build",
"prune": "rm -rf ./{packages,plugins}/*/{lib,esm,tsconfig.tsbuildinfo,package-lock.json}",
"storybook": "cross-env NODE_ENV=development BABEL_ENV=development start-storybook -p 6006",
"storybook": "cross-env NODE_ENV=development BABEL_ENV=development storybook dev -p 6006",
"tdd": "cross-env NODE_ENV=test jest --watch",
"test": "cross-env NODE_ENV=test jest",
"type": "tsc --noEmit",
@ -152,6 +152,7 @@
"json-stringify-pretty-compact": "^2.0.0",
"lodash": "^4.17.21",
"mapbox-gl": "^2.10.0",
"markdown-to-jsx": "^7.4.1",
"match-sorter": "^6.3.3",
"memoize-one": "^5.1.1",
"moment": "^2.30.1",
@ -212,10 +213,12 @@
"@babel/cli": "^7.22.6",
"@babel/compat-data": "^7.22.6",
"@babel/core": "^7.23.9",
"@babel/eslint-parser": "^7.22.7",
"@babel/eslint-parser": "^7.23.10",
"@babel/node": "^7.22.6",
"@babel/plugin-proposal-class-properties": "^7.18.6",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6",
"@babel/plugin-proposal-optional-chaining": "^7.21.0",
"@babel/plugin-proposal-private-methods": "^7.18.6",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-transform-runtime": "^7.22.7",
"@babel/preset-env": "^7.22.7",
@ -225,16 +228,17 @@
"@emotion/jest": "^11.3.0",
"@hot-loader/react-dom": "^16.13.0",
"@istanbuljs/nyc-config-typescript": "^1.0.1",
"@storybook/addon-actions": "^6.4.22",
"@storybook/addon-docs": "^6.5.10",
"@storybook/addon-essentials": "^6.4.22",
"@storybook/addon-knobs": "^6.3.1",
"@storybook/addon-links": "^6.4.22",
"@storybook/addons": "^6.4.22",
"@storybook/builder-webpack5": "^6.4.22",
"@storybook/client-api": "^6.4.22",
"@storybook/manager-webpack5": "^6.4.22",
"@storybook/react": "^6.4.22",
"@storybook/addon-actions": "^7.6.13",
"@storybook/addon-controls": "^7.6.13",
"@storybook/addon-docs": "^7.6.13",
"@storybook/addon-essentials": "^7.6.13",
"@storybook/addon-links": "^7.6.13",
"@storybook/addon-mdx-gfm": "^7.6.15",
"@storybook/addons": "^7.6.13",
"@storybook/client-api": "^7.6.13",
"@storybook/components": "^7.6.13",
"@storybook/react": "^7.6.13",
"@storybook/react-webpack5": "^7.6.13",
"@svgr/webpack": "^8.0.1",
"@testing-library/dom": "^7.29.4",
"@testing-library/jest-dom": "^5.11.6",
@ -259,6 +263,7 @@
"@types/react-loadable": "^5.5.6",
"@types/react-redux": "^7.1.10",
"@types/react-router-dom": "^5.3.3",
"@types/react-syntax-highlighter": "^15.5.11",
"@types/react-table": "^7.7.19",
"@types/react-transition-group": "^4.4.10",
"@types/react-ultimate-pagination": "^1.2.0",
@ -284,23 +289,26 @@
"css-minimizer-webpack-plugin": "^5.0.1",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.7",
"eslint": "^7.32.0",
"eslint-config-airbnb": "^18.2.1",
"eslint-config-prettier": "^7.1.0",
"esbuild": "^0.20.0",
"esbuild-loader": "^4.0.3",
"eslint": "^8.56.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-config-prettier": "^7.2.0",
"eslint-import-resolver-typescript": "^2.5.0",
"eslint-plugin-cypress": "^2.11.2",
"eslint-plugin-file-progress": "^1.2.0",
"eslint-plugin-import": "^2.24.2",
"eslint-plugin-jest": "^24.7.0",
"eslint-plugin-jest": "^27.8.0",
"eslint-plugin-jest-dom": "^3.6.5",
"eslint-plugin-jsx-a11y": "^6.4.1",
"eslint-plugin-lodash": "^7.4.0",
"eslint-plugin-no-only-tests": "^2.4.0",
"eslint-plugin-prettier": "^4.0.0",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-react": "^7.22.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-prefer-function-component": "^0.0.7",
"eslint-plugin-testing-library": "^3.10.2",
"eslint-plugin-storybook": "^0.6.15",
"eslint-plugin-testing-library": "^6.2.0",
"eslint-plugin-theme-colors": "file:tools/eslint-plugin-theme-colors",
"eslint-plugin-translation-vars": "file:tools/eslint-plugin-translation-vars",
"exports-loader": "^0.7.0",
@ -320,8 +328,8 @@
"mini-css-extract-plugin": "^2.7.6",
"mock-socket": "^9.3.1",
"node-fetch": "^2.6.7",
"prettier": "^2.4.1",
"prettier-plugin-packagejson": "^2.4.9",
"prettier": "3.1.0",
"prettier-plugin-packagejson": "^2.4.10",
"process": "^0.11.10",
"react-resizable": "^3.0.5",
"react-test-renderer": "^16.9.0",
@ -330,8 +338,8 @@
"source-map": "^0.7.4",
"source-map-support": "^0.5.21",
"speed-measure-webpack-plugin": "^1.5.0",
"storybook": "^7.6.13",
"storybook-addon-jsx": "^7.3.14",
"storybook-addon-paddings": "^4.3.0",
"style-loader": "^3.3.4",
"thread-loader": "^3.0.4",
"transform-loader": "^0.2.4",
@ -343,7 +351,8 @@
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.15.1",
"webpack-manifest-plugin": "^4.1.1",
"webpack-sources": "^3.2.3"
"webpack-sources": "^3.2.3",
"xdm": "^3.4.0"
},
"engines": {
"node": "^16.20.2",

View File

@ -83,9 +83,7 @@ export default function Select<VT extends string | number>({
minWidth,
}}
>
{options?.map(([val, label]) => (
<Option value={val}>{label}</Option>
))}
{options?.map(([val, label]) => <Option value={val}>{label}</Option>)}
{children}
{value && !optionsHasValue && (
<Option key={value} value={value}>

View File

@ -20,15 +20,16 @@ import { PostProcessingContribution } from '@superset-ui/core';
import { PostProcessingFactory } from './types';
/* eslint-disable @typescript-eslint/no-unused-vars */
export const contributionOperator: PostProcessingFactory<PostProcessingContribution> =
(formData, queryObject) => {
if (formData.contributionMode) {
return {
operation: 'contribution',
options: {
orientation: formData.contributionMode,
},
};
}
return undefined;
};
export const contributionOperator: PostProcessingFactory<
PostProcessingContribution
> = (formData, queryObject) => {
if (formData.contributionMode) {
return {
operation: 'contribution',
options: {
orientation: formData.contributionMode,
},
};
}
return undefined;
};

View File

@ -21,25 +21,26 @@ import { ComparisonType, PostProcessingCompare } from '@superset-ui/core';
import { getMetricOffsetsMap, isTimeComparison } from './utils';
import { PostProcessingFactory } from './types';
export const timeCompareOperator: PostProcessingFactory<PostProcessingCompare> =
(formData, queryObject) => {
const comparisonType = formData.comparison_type;
const metricOffsetMap = getMetricOffsetsMap(formData, queryObject);
export const timeCompareOperator: PostProcessingFactory<
PostProcessingCompare
> = (formData, queryObject) => {
const comparisonType = formData.comparison_type;
const metricOffsetMap = getMetricOffsetsMap(formData, queryObject);
if (
isTimeComparison(formData, queryObject) &&
comparisonType !== ComparisonType.Values
) {
return {
operation: 'compare',
options: {
source_columns: Array.from(metricOffsetMap.values()),
compare_columns: Array.from(metricOffsetMap.keys()),
compare_type: comparisonType,
drop_original_columns: true,
},
};
}
if (
isTimeComparison(formData, queryObject) &&
comparisonType !== ComparisonType.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;
};
return undefined;
};

View File

@ -27,31 +27,32 @@ import {
import { getMetricOffsetsMap, isTimeComparison } from './utils';
import { PostProcessingFactory } from './types';
export const timeComparePivotOperator: PostProcessingFactory<PostProcessingPivot> =
(formData, queryObject) => {
const metricOffsetMap = getMetricOffsetsMap(formData, queryObject);
const xAxisLabel = getXAxisLabel(formData);
const columns = queryObject.series_columns || queryObject.columns;
export const timeComparePivotOperator: PostProcessingFactory<
PostProcessingPivot
> = (formData, queryObject) => {
const metricOffsetMap = getMetricOffsetsMap(formData, queryObject);
const xAxisLabel = getXAxisLabel(formData);
const columns = queryObject.series_columns || queryObject.columns;
if (isTimeComparison(formData, queryObject) && xAxisLabel) {
const aggregates = Object.fromEntries(
[...metricOffsetMap.values(), ...metricOffsetMap.keys()].map(metric => [
metric,
// use the 'mean' aggregates to avoid drop NaN
{ operator: 'mean' as NumpyFunction },
]),
);
if (isTimeComparison(formData, queryObject) && xAxisLabel) {
const aggregates = Object.fromEntries(
[...metricOffsetMap.values(), ...metricOffsetMap.keys()].map(metric => [
metric,
// use the 'mean' aggregates to avoid drop NaN
{ operator: 'mean' as NumpyFunction },
]),
);
return {
operation: 'pivot',
options: {
index: [xAxisLabel],
columns: ensureIsArray(columns).map(getColumnLabel),
drop_missing_columns: !formData?.show_empty_columns,
aggregates,
},
};
}
return {
operation: 'pivot',
options: {
index: [xAxisLabel],
columns: ensureIsArray(columns).map(getColumnLabel),
drop_missing_columns: !formData?.show_empty_columns,
aggregates,
},
};
}
return undefined;
};
return undefined;
};

View File

@ -330,8 +330,8 @@ export type ControlConfig<
> = T extends InternalControlType
? SharedControlConfig<T, O>
: T extends object
? CustomControlConfig<T> // eslint-disable-next-line @typescript-eslint/no-explicit-any
: CustomControlConfig<any>;
? CustomControlConfig<T> // eslint-disable-next-line @typescript-eslint/no-explicit-any
: CustomControlConfig<any>;
/** ===========================================================
* Chart plugin control panel config
@ -526,36 +526,36 @@ export type ControlFormItemSpec<T extends ControlType = ControlType> = {
validators?: ControlFormValueValidator<string>[];
}
: T extends 'RadioButtonControl'
? {
options: [string, ReactNode][];
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>[];
}
: T extends 'CurrencyControl'
? {
controlType: 'CurrencyControl';
value?: Currency;
defaultValue?: Currency;
}
: {});
? {
options: [string, ReactNode][];
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>[];
}
: T extends 'CurrencyControl'
? {
controlType: 'CurrencyControl';
value?: Currency;
defaultValue?: Currency;
}
: {});

View File

@ -126,7 +126,7 @@ class ChartDataProvider extends React.PureComponent<
datasource,
formData,
queriesData,
} as Payload),
}) as Payload,
),
)
.then(this.handleReceiveData)

View File

@ -111,7 +111,6 @@ class SuperChart extends React.PureComponent<Props, {}> {
// Parse them in case they are % or 'auto'
const widthInfo = parseLength(width);
const heightInfo = parseLength(height);
const boxHeight = heightInfo.isDynamic
? `${heightInfo.multiplier * 100}%`
: heightInfo.value;

View File

@ -28,10 +28,10 @@ export default async function parseResponse<T extends ParseMethod = 'json'>(
type ReturnType = T extends 'raw' | null
? Response
: T extends 'json' | 'json-bigint' | undefined
? JsonResponse
: T extends 'text'
? TextResponse
: never;
? JsonResponse
: T extends 'text'
? TextResponse
: never;
const response = await apiPromise;
// reject failed HTTP requests with the raw response
if (!response.ok) {

View File

@ -28,8 +28,8 @@ import {
export type ParsedResponseType<T> = T extends 'text'
? string
: T extends 'raw' | null
? Response
: JsonValue;
? Response
: JsonValue;
/**
* Runtime options when calling a Superset API. Currently only allow overriding

View File

@ -42,13 +42,13 @@ const SET_OPERATORS = ['IN', 'NOT IN'] as const;
//---------------------------------------------------
/** An operator that does not require another operand */
export type UnaryOperator = typeof UNARY_OPERATORS[number];
export type UnaryOperator = (typeof UNARY_OPERATORS)[number];
/** An operator that requires another operand that is a single value */
export type BinaryOperator = typeof BINARY_OPERATORS[number];
export type BinaryOperator = (typeof BINARY_OPERATORS)[number];
/** An operator that require another operand that is a set */
export type SetOperator = typeof SET_OPERATORS[number];
export type SetOperator = (typeof SET_OPERATORS)[number];
//---------------------------------------------------
// Type guards

View File

@ -52,8 +52,8 @@ export const TestComponent = ({
style={{
width,
height,
backgroundColor: theme.colors.primary.base,
color: theme.colors.grayscale.light5,
backgroundColor: theme.colors.primary.light5,
color: theme.colors.grayscale.light3,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',

View File

@ -0,0 +1,18 @@
{
"sourceType": "unambiguous",
"presets": [
[
"@babel/preset-env",
{
"targets": {
"chrome": 100,
"safari": 15,
"firefox": 91
}
}
],
"@babel/preset-typescript",
"@babel/preset-react"
],
"plugins": []
}

View File

@ -1,16 +1,16 @@
import { dirname, join } from 'path';
const customConfig = require('../../../webpack.config.js');
module.exports = {
core: {
builder: 'webpack5',
},
addons: [
'@storybook/addon-knobs',
'storybook-addon-jsx',
'@storybook/addon-actions',
'@storybook/addon-links',
getAbsolutePath('@storybook/addon-controls'),
getAbsolutePath('storybook-addon-jsx'),
getAbsolutePath('@storybook/addon-actions'),
getAbsolutePath('@storybook/addon-links'),
],
stories: ['../storybook/stories/**/*Stories.[tj]sx'],
stories: ['../storybook/stories/**/*.stories.[tj]sx'],
webpackFinal: config => ({
...config,
module: {
@ -22,7 +22,21 @@ module.exports = {
...customConfig.resolve,
},
}),
typescript: {
reactDocgen: 'none',
},
framework: {
name: getAbsolutePath('@storybook/react-webpack5'),
options: {},
},
docs: {
autodocs: false,
},
};
function getAbsolutePath(value) {
return dirname(require.resolve(join(value, 'package.json')));
}

View File

@ -1,4 +1,3 @@
import { addParameters, addDecorator } from '@storybook/react';
import { jsxDecorator } from 'storybook-addon-jsx';
import {
configure,
@ -16,10 +15,9 @@ import themeDecorator from './themeDecorator';
import 'bootstrap/dist/css/bootstrap.min.css';
import './storybook.css';
addDecorator(jsxDecorator);
addDecorator(themeDecorator);
export const decorators = [jsxDecorator, themeDecorator];
addParameters({
export const parameters = {
passArgsFirst: false,
options: {
name: '✨ Superset UI',
@ -36,25 +34,25 @@ addParameters({
sortStoriesByKind: false,
url: '#',
storySort: (a, b) => {
if (a[1].kind === b[1].kind) {
if (a.kind === b.kind) {
return 0;
}
if (
a[1].id.startsWith('core-packages') &&
!b[1].id.startsWith('core-packages')
a.id.startsWith('core-packages') &&
!b.id.startsWith('core-packages')
) {
return -1;
}
if (
!a[1].id.startsWith('core-packages') &&
b[1].id.startsWith('core-packages')
!a.id.startsWith('core-packages') &&
b.id.startsWith('core-packages')
) {
return 1;
}
return a[1].id.localeCompare(b[1].id, undefined, { numeric: true });
return a.id.localeCompare(b.id, undefined, { numeric: true });
},
},
});
};
// Superset setup

View File

@ -2,7 +2,11 @@ html,
body,
#root {
height: 100%;
font-family: BlinkMacSystemFont, Roboto, Helvetica Neue, sans-serif;
font-family:
BlinkMacSystemFont,
Roboto,
Helvetica Neue,
sans-serif;
font-weight: 200;
color: #484848;
}

View File

@ -23,12 +23,12 @@
"license": "Apache-2.0",
"main": "index.js",
"scripts": {
"build-storybook": "npm run demo:clean && build-storybook",
"demo:build": "npm run demo:clean && build-storybook -o _gh-pages",
"build-storybook": "npm run demo:clean && storybook build",
"demo:build": "npm run demo:clean && storybook build -o _gh-pages",
"demo:clean": "rm -rf _gh-pages",
"demo:publish": "gh-pages -d _gh-pages",
"deploy-demo": "npm run demo:build && npm run demo:publish && npm run demo:clean",
"storybook": "start-storybook -p 9001"
"storybook": "storybook dev -p 9001"
},
"dependencies": {
"@data-ui/event-flow": "^0.0.84",
@ -36,11 +36,12 @@
"@emotion/react": "^11.4.1",
"@emotion/styled": "^11.3.0",
"@react-icons/all-files": "^4.1.0",
"@storybook/addon-actions": "^6.3.12",
"@storybook/addon-knobs": "^6.3.1",
"@storybook/addon-links": "^6.3.12",
"@storybook/addons": "^6.3.12",
"@storybook/react": "^6.3.12",
"@storybook/addon-actions": "^7.6.13",
"@storybook/addon-controls": "^7.6.13",
"@storybook/addon-links": "^7.6.13",
"@storybook/addons": "^7.6.13",
"@storybook/react": "^7.6.13",
"@storybook/types": "^7.6.13",
"@types/react-loadable": "^5.5.3",
"antd": "4.10.3",
"bootstrap": "^3.4.1",
@ -56,6 +57,10 @@
},
"devDependencies": {
"@babel/core": "^7.23.9",
"@babel/preset-env": "^7.23.9",
"@babel/preset-react": "^7.23.3",
"@babel/preset-typescript": "^7.23.3",
"@storybook/react-webpack5": "^7.6.13",
"babel-loader": "^8.1.0",
"chromatic": "^5.4.0",
"fork-ts-checker-webpack-plugin": "^5.0.7",

View File

@ -19,7 +19,7 @@
import React, { useState, ReactNode } from 'react';
import { styled } from '@superset-ui/core';
import { DecoratorFunction } from '@storybook/addons';
import { DecoratorFunction } from '@storybook/types';
import ResizablePanel, { Size } from './ResizablePanel';
export const SupersetBody = styled.div`
@ -70,7 +70,7 @@ export const withResizableChartDemo: DecoratorFunction<ReactNode> = (
initialSize={initialSize as Size | undefined}
panelPadding={panelPadding}
>
{innerSize => storyFn({ ...context, ...innerSize })}
{innerSize => storyFn({ ...context, ...context.args, ...innerSize })}
</ResizableChartDemo>
);
};

View File

@ -56,8 +56,10 @@ export default function ResizablePanel({
}
{...props}
>
{heading ? <div className="panel-heading">{heading}</div> : null}
<div className="panel-body">{children}</div>
<>
{heading ? <div className="panel-heading">{heading}</div> : null}
<div className="panel-body">{children}</div>
</>
</ResizableBox>
);
}

View File

@ -18,7 +18,6 @@
*/
import React from 'react';
import { text, select } from '@storybook/addon-knobs';
import {
SuperChart,
ChartDataProvider,
@ -40,19 +39,14 @@ export default function createQueryStory({
};
}) {
const keys = Object.keys(choices);
const story = () => {
const host = text(
'Set Superset App host for CORS request',
'localhost:8088',
);
const mode = select('Choose mode:', keys, keys[0]);
const { formData: presetFormData, chartType } = choices[mode];
const width = text('Vis width', '400');
const height = text('Vis height', '400');
const formData = text(
'Override formData',
JSON.stringify(presetFormData, null, 2),
);
const story = (
host: string,
mode: string | number,
width: number,
height: number,
formData: any,
) => {
const { chartType } = choices[mode];
return (
<div style={{ margin: 16 }}>
@ -99,5 +93,22 @@ export default function createQueryStory({
story.parameters = {
chromatic: { disable: true },
};
story.args = {
host: 'localhost:8088',
mode: keys[0],
width: '400',
height: '400',
formData: JSON.stringify(choices[keys[0]].formData, null, 2),
};
story.argTypes = {
host: {
control: 'text',
description: 'Superset App host for CORS request',
},
mode: { control: 'select', options: keys, description: 'Choose mode' },
width: { control: 'text', description: 'Vis width' },
height: { control: 'text', description: 'Vis height' },
formData: { control: 'text', description: 'Override formData' },
};
return story;
}

View File

@ -16,10 +16,11 @@
* specific language governing permissions and limitations
* under the License.
*/
import React, { useEffect, useState } from 'react';
import {
JsonObject,
seedRandom,
seed,
SuperChart,
SequentialD3,
useTheme,
@ -27,31 +28,37 @@ import {
import CountryMapChartPlugin, {
countries,
} from '@superset-ui/legacy-plugin-chart-country-map';
import { withKnobs, select } from '@storybook/addon-knobs';
import { withResizableChartDemo } from '../../../shared/components/ResizableChartDemo';
new CountryMapChartPlugin().configure({ key: 'country-map' }).register();
export default {
title: 'Legacy Chart Plugins/legacy-plugin-chart-country-map',
decorators: [withKnobs, withResizableChartDemo],
decorators: [withResizableChartDemo],
component: SuperChart,
parameters: {
initialSize: { width: 500, height: 300 },
},
};
function generateData(geojson: JsonObject) {
return geojson.features.map(feat => ({
metric: Math.round(seedRandom() * 10000) / 100,
metric: Math.round(Number(seed(feat.properties.ISO)()) * 10000) / 100,
country_id: feat.properties.ISO,
}));
}
export const basic = function BasicCountryMapStory({ width, height }) {
export const BasicCountryMapStory = (
{
country,
colorSchema,
}: {
country: string;
colorSchema: string;
},
{ width, height }: { width: number; height: number },
) => {
const theme = useTheme();
const country = select('Country', Object.keys(countries!), 'france');
const colorSchema = select<any>(
'Color schema',
SequentialD3,
SequentialD3.find(x => x.id === 'schemeOranges'),
);
const [data, setData] = useState<JsonObject>();
useEffect(() => {
@ -80,7 +87,6 @@ export const basic = function BasicCountryMapStory({ width, height }) {
</div>
);
}
return (
<SuperChart
chartType="country-map"
@ -88,10 +94,27 @@ export const basic = function BasicCountryMapStory({ width, height }) {
height={height}
queriesData={[{ data }]}
formData={{
linearColorScheme: colorSchema.id,
linearColorScheme: colorSchema,
numberFormat: '.3s',
selectCountry: country,
}}
/>
);
};
BasicCountryMapStory.args = {
country: 'finland',
colorSchema: 'schemeOranges',
};
BasicCountryMapStory.argTypes = {
country: {
control: 'select',
options: Object.keys(countries),
},
colorSchema: {
control: 'select',
options: SequentialD3.map(x => x.id),
description: 'Choose a color schema',
defaultValue: 'schemeOranges',
},
};

View File

@ -53,9 +53,7 @@ export const stackedWithYAxisBounds = () => (
/>
);
stackedWithYAxisBounds.story = {
name: 'Stacked with yAxisBounds',
};
stackedWithYAxisBounds.storyName = 'Stacked with yAxisBounds';
export const stackedWithYAxisBoundsMinOnly = () => (
<SuperChart
@ -88,6 +86,4 @@ export const stackedWithYAxisBoundsMinOnly = () => (
/>
);
stackedWithYAxisBoundsMinOnly.story = {
name: 'Stacked with yAxisBounds min only',
};
stackedWithYAxisBoundsMinOnly.storyName = 'Stacked with yAxisBounds min only';

View File

@ -0,0 +1,198 @@
/*
* 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 { SuperChart, getChartTransformPropsRegistry } from '@superset-ui/core';
import {
EchartsAreaChartPlugin,
TimeseriesTransformProps,
} from '@superset-ui/plugin-chart-echarts';
import data from './data';
import { withResizableChartDemo } from '../../../../shared/components/ResizableChartDemo';
new EchartsAreaChartPlugin().configure({ key: 'echarts_area' }).register();
getChartTransformPropsRegistry().registerValue(
'echarts_area',
TimeseriesTransformProps,
);
export default {
title: 'Chart Plugins/plugin-chart-echarts',
decorators: [withResizableChartDemo],
component: SuperChart,
parameters: {
initialSize: { width: 500, height: 300 },
},
args: {
forecastEnabled: true,
seriesType: 'line',
show_extra_controls: false,
logAxis: false,
stack: false,
showValue: false,
onlyTotal: false,
percentageThreshold: 0,
markerEnabled: false,
markerSize: 6,
minorSplitLine: false,
opacity: 0.2,
zoomable: false,
},
argTypes: {
forecastEnabled: {
control: 'boolean',
description: 'Extra Forecast',
defaultValue: false,
},
seriesType: {
control: 'select',
description: 'Line type',
options: ['line', 'scatter', 'smooth', 'bar', 'start', 'middle', 'end'],
},
show_extra_controls: {
control: 'boolean',
description: 'Extra Controls',
defaultValue: false,
},
logAxis: {
control: 'boolean',
description: 'Log axis',
defaultValue: false,
},
stack: {
control: 'boolean',
defaultValue: false,
},
showValue: {
control: 'boolean',
description: 'Show Values',
defaultValue: false,
},
onlyTotal: {
control: 'boolean',
description: 'Only Total',
defaultValue: false,
},
percentageThreshold: {
control: { type: 'number', min: 0, max: 100, step: 1 },
description: 'Percentage Threshold',
defaultValue: 0,
},
markerEnabled: {
control: 'boolean',
description: 'Enable markers',
defaultValue: false,
},
markerSize: {
control: { type: 'number', min: 0, max: 100, step: 1 },
description: 'Marker Size',
defaultValue: 6,
},
minorSplitLine: {
control: 'boolean',
description: 'Minor splitline',
defaultValue: false,
},
opacity: {
control: { type: 'number', min: 0, max: 1, step: 0.1 },
description: 'Opacity',
defaultValue: 0.2,
},
zoomable: {
control: 'boolean',
description: 'Zoomable',
defaultValue: false,
},
},
};
export const AreaSeries = (
{
forecastEnabled,
seriesType,
show_extra_controls,
logAxis,
stack,
showValue,
onlyTotal,
percentageThreshold,
markerEnabled,
markerSize,
minorSplitLine,
opacity,
zoomable,
}: {
forecastEnabled: boolean;
seriesType: string;
show_extra_controls: boolean;
logAxis: boolean;
stack: boolean;
showValue: boolean;
onlyTotal: boolean;
percentageThreshold: number;
markerEnabled: boolean;
markerSize: number;
minorSplitLine: boolean;
opacity: number;
zoomable: boolean;
},
{ width, height }: { width: number; height: number },
) => {
const queryData = data
.map(row =>
forecastEnabled
? row
: {
// eslint-disable-next-line no-underscore-dangle
__timestamp: row.__timestamp,
Boston: row.Boston,
California: row.California,
WestTexNewMexico: row.WestTexNewMexico,
},
)
.filter(row => forecastEnabled || !!row.Boston);
return (
<SuperChart
chartType="echarts_area"
width={width}
height={height}
queriesData={[{ data: queryData }]}
formData={{
area: true,
contributionMode: undefined,
forecastEnabled,
colorScheme: 'supersetColors',
seriesType,
show_extra_controls,
logAxis,
yAxisFormat: 'SMART_NUMBER',
stack,
showValue,
onlyTotal,
percentageThreshold,
markerEnabled,
markerSize,
minorSplitLine,
opacity,
zoomable,
}}
/>
);
};

View File

@ -1,88 +0,0 @@
/*
* 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 { SuperChart, getChartTransformPropsRegistry } from '@superset-ui/core';
import { boolean, number, select, withKnobs } from '@storybook/addon-knobs';
import {
EchartsAreaChartPlugin,
TimeseriesTransformProps,
} from '@superset-ui/plugin-chart-echarts';
import data from './data';
import { withResizableChartDemo } from '../../../../shared/components/ResizableChartDemo';
new EchartsAreaChartPlugin().configure({ key: 'echarts_area' }).register();
getChartTransformPropsRegistry().registerValue(
'echarts_area',
TimeseriesTransformProps,
);
export default {
title: 'Chart Plugins/plugin-chart-echarts/Timeseries Area',
decorators: [withKnobs, withResizableChartDemo],
};
export const Timeseries = ({ width, height }) => {
const forecastEnabled = boolean('Enable forecast', true);
const queryData = data
.map(row =>
forecastEnabled
? row
: {
// eslint-disable-next-line no-underscore-dangle
__timestamp: row.__timestamp,
Boston: row.Boston,
California: row.California,
WestTexNewMexico: row.WestTexNewMexico,
},
)
.filter(row => forecastEnabled || !!row.Boston);
return (
<SuperChart
chartType="echarts_area"
width={width}
height={height}
queriesData={[{ data: queryData }]}
formData={{
area: true,
contributionMode: undefined,
forecastEnabled,
colorScheme: 'supersetColors',
seriesType: select(
'Line type',
['line', 'scatter', 'smooth', 'bar', 'start', 'middle', 'end'],
'line',
),
show_extra_controls: boolean('Extra Controls', false),
logAxis: boolean('Log axis', false),
yAxisFormat: 'SMART_NUMBER',
stack: boolean('Stack', false),
showValue: boolean('Show Values', false),
onlyTotal: boolean('Only Total', false),
percentageThreshold: number('Percentage Threshold', 0),
markerEnabled: boolean('Enable markers', false),
markerSize: number('Marker Size', 6),
minorSplitLine: boolean('Minor splitline', false),
opacity: number('Opacity', 0.2),
zoomable: boolean('Zoomable', false),
}}
/>
);
};

View File

@ -19,7 +19,6 @@
import React from 'react';
import { SuperChart, getChartTransformPropsRegistry } from '@superset-ui/core';
import { select, withKnobs } from '@storybook/addon-knobs';
import {
EchartsBoxPlotChartPlugin,
BoxPlotTransformProps,
@ -38,10 +37,27 @@ getChartTransformPropsRegistry().registerValue(
export default {
title: 'Chart Plugins/plugin-chart-echarts/BoxPlot',
decorators: [withKnobs, withResizableChartDemo],
decorators: [withResizableChartDemo],
args: {
xTicksLayout: '45°', // Initial value
},
argTypes: {
xTicksLayout: {
control: 'select',
options: ['auto', 'flat', '45°', '90°', 'staggered'],
defaultValue: '45°', // Default value here
},
},
};
export const BoxPlot = ({ width, height }) => (
export const BoxPlot = (
{
xTicksLayout,
}: {
xTicksLayout: string;
},
{ width, height }: { width: number; height: number },
) => (
<SuperChart
chartType="echarts-boxplot"
width={width}
@ -52,11 +68,7 @@ export const BoxPlot = ({ width, height }) => (
groupby: ['type', 'region'],
metrics: ['AVG(averageprice)'],
whiskerOptions: 'Tukey',
xTicksLayout: select(
'X Tick Layout',
['auto', 'flat', '45°', '90°', 'staggered'],
'45°',
),
xTicksLayout,
yAxisFormat: 'SMART_NUMBER',
}}
/>

View File

@ -17,18 +17,11 @@
* under the License.
*/
import React from 'react';
import { SuperChart, getChartTransformPropsRegistry } from '@superset-ui/core';
import {
boolean,
number,
select,
text,
withKnobs,
} from '@storybook/addon-knobs';
import {
EchartsBubbleChartPlugin,
BubbleTransformProps,
} from '@superset-ui/plugin-chart-echarts';
import { SuperChart, getChartTransformPropsRegistry } from '@superset-ui/core';
import { simpleBubbleData } from './data';
import { withResizableChartDemo } from '../../../../shared/components/ResizableChartDemo';
@ -40,11 +33,77 @@ getChartTransformPropsRegistry().registerValue(
);
export default {
title: 'Chart Plugins/plugin-chart-echarts/Bubble',
decorators: [withKnobs, withResizableChartDemo],
title: 'Chart Plugins/plugin-chart-echarts',
decorators: [withResizableChartDemo],
args: {
maxBubbleSize: 10,
xAxisTitle: '',
xAxisTitleMargin: 30,
yAxisTitle: '',
yAxisTitleMargin: 30,
logYAxis: false,
logXAxis: false,
},
argTypes: {
maxBubbleSize: {
control: 'select',
options: [5, 10, 25, 50, 100, 125],
name: 'Max Bubble Size',
description: 'Maximum size of bubbles',
},
xAxisTitle: {
control: 'text',
name: 'X Axis Title',
description: 'Title for the X axis',
},
xAxisTitleMargin: {
control: 'number',
name: 'X Axis Title Margin',
description: 'Margin for the X axis title',
},
yAxisTitle: {
control: 'text',
name: 'Y Axis Title',
description: 'Title for the Y axis',
},
yAxisTitleMargin: {
control: 'number',
name: 'Y Axis Title Margin',
description: 'Margin for the Y axis title',
},
logYAxis: {
control: 'boolean',
name: 'Log Y Axis',
description: 'Whether to use a logarithmic scale for the Y axis',
},
logXAxis: {
control: 'boolean',
name: 'Log X Axis',
description: 'Whether to use a logarithmic scale for the X axis',
},
},
};
export const SimpleBubble = ({ width, height }) => (
export const BubbleChart = (
{
maxBubbleSize,
xAxisTitle,
xAxisTitleMargin,
yAxisTitle,
yAxisTitleMargin,
logYAxis,
logXAxis,
}: {
maxBubbleSize: number;
xAxisTitle: string;
xAxisTitleMargin: number;
yAxisTitle: string;
yAxisTitleMargin: number;
logYAxis: boolean;
logXAxis: boolean;
},
{ width, height }: { width: number; height: number },
) => (
<SuperChart
chartType="bubble_v2"
width={width}
@ -110,16 +169,16 @@ export const SimpleBubble = ({ width, height }) => (
},
limit: 10,
colorScheme: 'supersetColors',
maxBubbleSize: select('Max bubble size', [5, 10, 25, 50, 100, 125], 10),
xAxisTitle: text('X axis title', ''),
xAxisTitleMargin: number('X axis title margin', 30),
yAxisTitle: text('Y axis title', ''),
yAxisTitleMargin: number('Y axis title margin', 30),
maxBubbleSize,
xAxisTitle,
xAxisTitleMargin,
yAxisTitle,
yAxisTitleMargin,
yAxisTitlePosition: 'Left',
xAxisFormat: null,
logYAxis: boolean('Log Y axis', false),
logYAxis,
yAxisFormat: null,
logXAxis: boolean('Log X axis', false),
logXAxis,
truncateYAxis: false,
yAxisBounds: [],
extraFormData: {},

View File

@ -19,7 +19,6 @@
import React from 'react';
import { SuperChart, getChartTransformPropsRegistry } from '@superset-ui/core';
import { boolean, number, select, withKnobs } from '@storybook/addon-knobs';
import {
EchartsFunnelChartPlugin,
FunnelTransformProps,
@ -36,10 +35,59 @@ getChartTransformPropsRegistry().registerValue(
export default {
title: 'Chart Plugins/plugin-chart-echarts/Funnel',
decorators: [withKnobs, withResizableChartDemo],
decorators: [withResizableChartDemo],
args: {
orient: 'vertical',
sort: 'descending',
gap: 0,
labelType: 'key',
labelLine: true,
showLabels: true,
showLegend: false,
},
argTypes: {
width: { control: 'number' },
height: { control: 'number' },
orient: { control: 'select', options: ['horizontal', 'vertical'] },
sort: { control: 'select', options: ['descending', 'ascending', 'none'] },
gap: { control: 'number' },
labelType: {
control: 'select',
options: [
'key',
'value',
'percent',
'key_value',
'key_percent',
'key_value_percent',
],
},
labelLine: { control: 'boolean' },
showLabels: { control: 'boolean' },
showLegend: { control: 'boolean' },
},
};
export const Funnel = ({ width, height }) => (
export const Funnel = (
{
orient,
sort,
gap,
labelType,
labelLine,
showLabels,
showLegend,
}: {
orient: string;
sort: string;
gap: number;
labelType: string;
labelLine: boolean;
showLabels: boolean;
showLegend: boolean;
},
{ width, height }: { width: number; height: number },
) => (
<SuperChart
chartType="echarts-funnel"
width={width}
@ -50,24 +98,13 @@ export const Funnel = ({ width, height }) => (
groupby: ['name'],
metric: 'value',
numberFormat: 'SMART_NUMBER',
orient: select('orient', ['horizontal', 'vertical'], 'vertical'),
sort: select('sort', ['descending', 'ascending', 'none'], 'descending'),
gap: number('gap', 0),
labelType: select(
'label type',
[
'key',
'value',
'percent',
'key_value',
'key_percent',
'key_value_percent',
],
'key',
),
labelLine: boolean('Label line', true),
showLabels: boolean('Show labels', true),
showLegend: boolean('Show legend', false),
orient,
sort,
gap,
labelType,
labelLine,
showLabels,
showLegend,
}}
/>
);

View File

@ -19,7 +19,6 @@
import React from 'react';
import { SuperChart, getChartTransformPropsRegistry } from '@superset-ui/core';
import { withKnobs } from '@storybook/addon-knobs';
import {
EchartsGaugeChartPlugin,
GaugeTransformProps,
@ -36,7 +35,7 @@ getChartTransformPropsRegistry().registerValue(
export default {
title: 'Chart Plugins/plugin-chart-echarts/Gauge',
decorators: [withKnobs, withResizableChartDemo],
decorators: [withResizableChartDemo],
};
export const Gauge = ({ width, height }) => (

View File

@ -19,7 +19,6 @@
import React from 'react';
import { SuperChart, getChartTransformPropsRegistry } from '@superset-ui/core';
import { withKnobs } from '@storybook/addon-knobs';
import {
EchartsGraphChartPlugin,
GraphTransformProps,
@ -36,7 +35,7 @@ getChartTransformPropsRegistry().registerValue(
export default {
title: 'Chart Plugins/plugin-chart-echarts/Graph',
decorators: [withKnobs, withResizableChartDemo],
decorators: [withResizableChartDemo],
};
export const Graph = ({ width, height }) => (

View File

@ -0,0 +1,352 @@
/*
* 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 { SuperChart, getChartTransformPropsRegistry } from '@superset-ui/core';
import {
EchartsTimeseriesChartPlugin,
MixedTimeseriesTransformProps,
} from '@superset-ui/plugin-chart-echarts';
import data from '../Timeseries/data';
import negativeNumData from './negativeData';
import { withResizableChartDemo } from '../../../../shared/components/ResizableChartDemo';
new EchartsTimeseriesChartPlugin()
.configure({ key: 'mixed-timeseries' })
.register();
getChartTransformPropsRegistry().registerValue(
'mixed-timeseries',
MixedTimeseriesTransformProps,
);
export default {
title: 'Chart Plugins/plugin-chart-echarts/MixedTimeseries',
decorators: [withResizableChartDemo],
};
export const Timeseries = (
{
zoomable,
logAxis,
yAxisFormat,
yAxisTitle,
yAxisIndexB,
minorSplitLine,
seriesType,
stack,
area,
markerEnabled,
markerSize,
opacity,
seriesTypeB,
stackB,
areaB,
markerEnabledB,
markerSizeB,
opacityB,
}: {
zoomable: boolean;
logAxis: boolean;
yAxisFormat: string;
yAxisTitle: string;
yAxisIndexB: number;
minorSplitLine: boolean;
seriesType: string;
stack: boolean;
area: boolean;
markerEnabled: boolean;
markerSize: number;
opacity: number;
seriesTypeB: string;
stackB: boolean;
areaB: boolean;
markerEnabledB: boolean;
markerSizeB: number;
opacityB: number;
},
{ width, height }: { width: number; height: number },
) => {
const queriesData = [
{
data: data
.map(row => ({
// eslint-disable-next-line no-underscore-dangle
__timestamp: row.__timestamp,
Boston: row.Boston,
}))
.filter(row => !!row.Boston),
colnames: ['__timestamp'],
coltypes: [2],
},
{
data: data
.map(row => ({
// eslint-disable-next-line no-underscore-dangle
__timestamp: row.__timestamp,
California: row.California,
WestTexNewMexico: row.WestTexNewMexico,
}))
.filter(row => !!row.California),
},
];
return (
<SuperChart
chartType="mixed-timeseries"
width={width}
height={height}
queriesData={queriesData}
formData={{
contributionMode: undefined,
colorScheme: 'supersetColors',
zoomable,
logAxis,
xAxisTimeFormat: 'smart_date',
tooltipTimeFormat: 'smart_date',
yAxisFormat,
yAxisTitle,
yAxisIndexB,
minorSplitLine,
seriesType,
stack,
area,
markerEnabled,
markerSize,
opacity,
seriesTypeB,
stackB,
areaB,
markerEnabledB,
markerSizeB,
opacityB,
showValue: true,
}}
/>
);
};
Timeseries.args = {
zoomable: false,
logAxis: false,
yAxisFormat: '$,.2f',
yAxisTitle: '',
yAxisIndexB: 1,
minorSplitLine: false,
seriesType: 'line',
stack: false,
area: false,
markerSize: 6,
opacity: 0.2,
seriesTypeB: 'bar',
stackB: false,
areaB: false,
markerEnabledB: false,
markerSizeB: 6,
opacityB: 0.2,
};
Timeseries.argTypes = {
zoomable: {
control: 'boolean',
description: 'Zoomable',
defaultValue: false,
},
logAxis: {
control: 'boolean',
description: 'Log axis',
defaultValue: false,
},
yAxisFormat: {
control: 'select',
description: 'Y Axis format',
options: ['$,.2f', 'SMART_NUMBER'],
defaultValue: '$,.2f',
},
yAxisTitle: {
control: 'text',
description: 'Y Axis title',
defaultValue: '',
},
yAxisIndexB: {
control: 'select',
description: 'Y Axis index for Query 2',
options: [0, 1],
defaultValue: 1,
},
minorSplitLine: {
control: 'boolean',
description: 'Query 1: Minor splitline',
defaultValue: false,
},
seriesType: {
control: 'select',
description: 'Query 1: Line type',
options: ['line', 'scatter', 'smooth', 'bar', 'start', 'middle', 'end'],
defaultValue: 'line',
},
stack: {
control: 'boolean',
description: 'Query 1: Stack',
defaultValue: false,
},
area: {
control: 'boolean',
description: 'Query 1: Area chart',
defaultValue: false,
},
markerEnabled: {
control: 'boolean',
description: 'Query 1: Enable markers',
defaultValue: false,
},
markerSize: {
control: 'number',
description: 'Query 1: Marker Size',
defaultValue: 6,
},
opacity: {
control: 'number',
description: 'Query 1: Opacity',
defaultValue: 0.2,
},
seriesTypeB: {
control: 'select',
description: 'Query 2: Line type',
options: ['line', 'scatter', 'smooth', 'bar', 'start', 'middle', 'end'],
defaultValue: 'bar',
},
stackB: {
control: 'boolean',
description: 'Query 2: Stack',
defaultValue: false,
},
areaB: {
control: 'boolean',
description: 'Query 2: Area chart',
defaultValue: false,
},
markerEnabledB: {
control: 'boolean',
description: 'Query 2: Enable markers',
defaultValue: false,
},
markerSizeB: {
control: 'number',
description: 'Query 2: Marker Size',
defaultValue: 6,
},
opacityB: {
control: 'number',
description: 'Query 2: Opacity',
defaultValue: 0.2,
},
};
export const WithNegativeNumbers = (
{
seriesType,
yAxisFormat,
showValue,
showValueB,
yAxisIndexB,
}: {
seriesType: string;
yAxisFormat: string;
showValue: boolean;
showValueB: boolean;
yAxisIndexB: number;
},
{ width, height }: { width: number; height: number },
) => (
<SuperChart
chartType="mixed-timeseries"
width={width}
height={height}
queriesData={[
{
data: negativeNumData,
colnames: ['__timestamp'],
coltypes: [2],
},
{
data: negativeNumData.map(({ __timestamp, Boston }) => ({
__timestamp,
avgRate: Boston / 100,
})),
},
]}
formData={{
contributionMode: undefined,
colorScheme: 'supersetColors',
seriesType,
xAxisTimeFormat: 'smart_date',
yAxisFormat,
stack: true,
showValue,
showValueB,
showLegend: true,
markerEnabledB: true,
yAxisIndexB,
}}
/>
);
WithNegativeNumbers.args = {
width: 400,
height: 400,
seriesType: 'line',
yAxisFormat: '$,.2f',
showValue: true,
showValueB: false,
yAxisIndexB: 1,
};
WithNegativeNumbers.argTypes = {
seriesType: {
control: 'select',
options: ['line', 'scatter', 'smooth', 'bar', 'start', 'middle', 'end'],
},
yAxisFormat: {
control: 'select',
options: {
'Original value': '~g',
'Smart number': 'SMART_NUMBER',
'(12345.432 => $12,345.43)': '$,.2f',
},
},
showValue: {
control: 'boolean',
description: 'Query 1: Show Value',
defaultValue: true,
},
showValueB: {
control: 'boolean',
description: 'Query 2: Show Value',
defaultValue: false,
},
yAxisIndexB: {
control: 'select',
description: 'Query 2: Y Axis',
options: {
Primary: 0,
Secondary: 1,
},
defaultValue: 1,
},
};

View File

@ -1,173 +0,0 @@
/*
* 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 { SuperChart, getChartTransformPropsRegistry } from '@superset-ui/core';
import {
boolean,
number,
text,
select,
withKnobs,
} from '@storybook/addon-knobs';
import {
EchartsTimeseriesChartPlugin,
MixedTimeseriesTransformProps,
} from '@superset-ui/plugin-chart-echarts';
import data from '../Timeseries/data';
import negativeNumData from './negativeData';
import { withResizableChartDemo } from '../../../../shared/components/ResizableChartDemo';
new EchartsTimeseriesChartPlugin()
.configure({ key: 'mixed-timeseries' })
.register();
getChartTransformPropsRegistry().registerValue(
'mixed-timeseries',
MixedTimeseriesTransformProps,
);
export default {
title: 'Chart Plugins/plugin-chart-echarts/MixedTimeseries',
decorators: [withKnobs, withResizableChartDemo],
};
export const Timeseries = ({ width, height }) => {
const queriesData = [
{
data: data
.map(row => ({
// eslint-disable-next-line no-underscore-dangle
__timestamp: row.__timestamp,
Boston: row.Boston,
}))
.filter(row => !!row.Boston),
colnames: ['__timestamp'],
coltypes: [2],
},
{
data: data
.map(row => ({
// eslint-disable-next-line no-underscore-dangle
__timestamp: row.__timestamp,
California: row.California,
WestTexNewMexico: row.WestTexNewMexico,
}))
.filter(row => !!row.California),
},
];
return (
<SuperChart
chartType="mixed-timeseries"
width={width}
height={height}
queriesData={queriesData}
formData={{
contributionMode: undefined,
colorScheme: 'supersetColors',
zoomable: boolean('Zoomable', false),
logAxis: boolean('Log axis', false),
xAxisTimeFormat: 'smart_date',
tooltipTimeFormat: 'smart_date',
yAxisFormat: select(
'y-axis format',
['$,.2f', 'SMART_NUMBER'],
'$,.2f',
),
yAxisTitle: text('Y Axis title', ''),
yAxisIndexB: select('yAxisIndexB', [0, 1], 1),
minorSplitLine: boolean('Query 1: Minor splitline', false),
seriesType: select(
'Query 1: Line type',
['line', 'scatter', 'smooth', 'bar', 'start', 'middle', 'end'],
'line',
),
stack: boolean('Query 1: Stack', false),
area: boolean('Query 1: Area chart', false),
markerEnabled: boolean('Query 1: Enable markers', false),
markerSize: number('Query 1: Marker Size', 6),
opacity: number('Query 1: Opacity', 0.2),
seriesTypeB: select(
'Query 2: Line type',
['line', 'scatter', 'smooth', 'bar', 'start', 'middle', 'end'],
'bar',
),
stackB: boolean('Query 2: Stack', false),
areaB: boolean('Query 2: Area chart', false),
markerEnabledB: boolean('Query 2: Enable markers', false),
markerSizeB: number('Query 2: Marker Size', 6),
opacityB: number('Query 2: Opacity', 0.2),
showValue: true,
}}
/>
);
};
export const WithNegativeNumbers = ({ width, height }) => (
<SuperChart
chartType="mixed-timeseries"
width={width}
height={height}
queriesData={[
{
data: negativeNumData,
colnames: ['__timestamp'],
coltypes: [2],
},
{
data: negativeNumData.map(({ __timestamp, Boston }) => ({
__timestamp,
avgRate: Boston / 100,
})),
},
]}
formData={{
contributionMode: undefined,
colorScheme: 'supersetColors',
seriesType: select(
'Line type',
['line', 'scatter', 'smooth', 'bar', 'start', 'middle', 'end'],
'line',
),
xAxisTimeFormat: 'smart_date',
yAxisFormat: select(
'y-axis format',
{
'Original value': '~g',
'Smart number': 'SMART_NUMBER',
'(12345.432 => $12,345.43)': '$,.2f',
},
'$,.2f',
),
stack: true,
showValue: boolean('Query 1: Show Value', true),
showValueB: boolean('Query 2: Show Value', false),
showLegend: true,
markerEnabledB: true,
yAxisIndexB: select(
'Query 2: Y Axis',
{
Primary: 0,
Secondary: 1,
},
1,
),
}}
/>
);

View File

@ -0,0 +1,195 @@
/*
* 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 { SuperChart, getChartTransformPropsRegistry } from '@superset-ui/core';
import {
EchartsPieChartPlugin,
PieTransformProps,
} from '@superset-ui/plugin-chart-echarts';
import { weekday, population } from './data';
import { withResizableChartDemo } from '../../../../shared/components/ResizableChartDemo';
new EchartsPieChartPlugin().configure({ key: 'echarts-pie' }).register();
getChartTransformPropsRegistry().registerValue(
'echarts-pie',
PieTransformProps,
);
export default {
title: 'Chart Plugins/plugin-chart-echarts/Pie',
decorators: [withResizableChartDemo],
};
export const WeekdayPie = (
{
donut,
innerRadius,
outerRadius,
labelsOutside,
labelLine,
showLabels,
showLegend,
labelType,
}: {
donut: boolean;
innerRadius: number;
outerRadius: number;
labelsOutside: boolean;
labelLine: boolean;
showLabels: boolean;
showLegend: boolean;
labelType: string;
},
{ width, height }: { width: number; height: number },
) => (
<SuperChart
chartType="echarts-pie"
width={width}
height={height}
queriesData={[{ data: weekday }]}
formData={{
colorScheme: 'supersetColors',
groupby: ['Day'],
metric: 'SUM(AIR_TIME)',
numberFormat: 'SMART_NUMBER',
donut,
innerRadius,
outerRadius,
labelsOutside,
labelLine,
showLabels,
showLegend,
labelType,
}}
/>
);
WeekdayPie.args = {
donut: false,
innerRadius: 30,
outerRadius: 70,
labelsOutside: true,
labelLine: true,
showLabels: true,
showLegend: false,
labelType: 'key',
};
WeekdayPie.argTypes = {
donut: { control: 'boolean' },
innerRadius: { control: 'number' },
outerRadius: { control: 'number' },
labelsOutside: { control: 'boolean' },
labelLine: { control: 'boolean' },
showLabels: { control: 'boolean' },
showLegend: { control: 'boolean' },
labelType: {
control: {
type: 'select',
options: [
'key',
'value',
'percent',
'key_value',
'key_percent',
'key_value_percent',
],
},
},
};
export const PopulationPie = (
{
donut,
innerRadius,
outerRadius,
labelsOutside,
labelLine,
showLabels,
showLegend,
labelType,
}: {
donut: boolean;
innerRadius: number;
outerRadius: number;
labelsOutside: boolean;
labelLine: boolean;
showLabels: boolean;
showLegend: boolean;
labelType: string;
},
{ width, height }: { width: number; height: number },
) => (
<SuperChart
chartType="echarts-pie"
width={width}
height={height}
queriesData={[{ data: population }]}
formData={{
colorScheme: 'supersetColors',
groupby: ['Country'],
metric: 'Population',
numberFormat: 'SMART_NUMBER',
donut,
innerRadius,
outerRadius,
labelsOutside,
labelLine,
showLabels,
showLegend,
labelType,
}}
/>
);
PopulationPie.args = {
donut: false,
innerRadius: 30,
outerRadius: 70,
labelsOutside: false,
labelLine: true,
showLabels: true,
showLegend: false,
labelType: 'key',
};
PopulationPie.argTypes = {
donut: { control: 'boolean' },
innerRadius: { control: 'number' },
outerRadius: { control: 'number' },
labelsOutside: { control: 'boolean' },
labelLine: { control: 'boolean' },
showLabels: { control: 'boolean' },
showLegend: { control: 'boolean' },
labelType: {
control: {
type: 'select',
options: [
'key',
'value',
'percent',
'key_value',
'key_percent',
'key_value_percent',
],
},
},
};

View File

@ -1,108 +0,0 @@
/*
* 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 { SuperChart, getChartTransformPropsRegistry } from '@superset-ui/core';
import { boolean, number, select, withKnobs } from '@storybook/addon-knobs';
import {
EchartsPieChartPlugin,
PieTransformProps,
} from '@superset-ui/plugin-chart-echarts';
import { weekday, population } from './data';
import { withResizableChartDemo } from '../../../../shared/components/ResizableChartDemo';
new EchartsPieChartPlugin().configure({ key: 'echarts-pie' }).register();
getChartTransformPropsRegistry().registerValue(
'echarts-pie',
PieTransformProps,
);
export default {
title: 'Chart Plugins/plugin-chart-echarts/Pie',
decorators: [withKnobs, withResizableChartDemo],
};
export const WeekdayPie = ({ width, height }) => (
<SuperChart
chartType="echarts-pie"
width={width}
height={height}
queriesData={[{ data: weekday }]}
formData={{
colorScheme: 'supersetColors',
groupby: ['Day'],
metric: 'SUM(AIR_TIME)',
numberFormat: 'SMART_NUMBER',
donut: boolean('Donut', false),
innerRadius: number('Inner Radius', 30),
outerRadius: number('Outer Radius', 70),
labelsOutside: boolean('Labels outside', true),
labelLine: boolean('Label line', true),
showLabels: boolean('Show labels', true),
showLegend: boolean('Show legend', false),
labelType: select(
'Pie label type',
[
'key',
'value',
'percent',
'key_value',
'key_percent',
'key_value_percent',
],
'key',
),
}}
/>
);
export const PopulationPie = ({ width, height }) => (
<SuperChart
chartType="echarts-pie"
width={width}
height={height}
queriesData={[{ data: population }]}
formData={{
colorScheme: 'supersetColors',
groupby: ['Country'],
metric: 'Population',
numberFormat: 'SMART_NUMBER',
donut: boolean('Donut', false),
innerRadius: number('Inner Radius', 30),
outerRadius: number('Outer Radius', 70),
labelsOutside: boolean('Labels outside', false),
labelLine: boolean('Label line', true),
showLabels: boolean('Show labels', true),
showLegend: boolean('Show legend', false),
labelType: select(
'Pie label type',
[
'key',
'value',
'percent',
'key_value',
'key_percent',
'key_value_percent',
],
'key',
),
}}
/>
);

View File

@ -19,7 +19,6 @@
import React from 'react';
import { SuperChart, getChartTransformPropsRegistry } from '@superset-ui/core';
import { withKnobs } from '@storybook/addon-knobs';
import {
EchartsRadarChartPlugin,
RadarTransformProps,
@ -36,7 +35,7 @@ getChartTransformPropsRegistry().registerValue(
export default {
title: 'Chart Plugins/plugin-chart-echarts/Radar',
decorators: [withKnobs, withResizableChartDemo],
decorators: [withResizableChartDemo],
};
export const Radar = ({ width, height }) => (

View File

@ -19,7 +19,6 @@
import React from 'react';
import { SuperChart, getChartTransformPropsRegistry } from '@superset-ui/core';
import { boolean, withKnobs } from '@storybook/addon-knobs';
import {
EchartsSunburstChartPlugin,
SunburstTransformProps,
@ -38,10 +37,19 @@ getChartTransformPropsRegistry().registerValue(
export default {
title: 'Chart Plugins/plugin-chart-echarts/Sunburst',
decorators: [withKnobs, withResizableChartDemo],
decorators: [withResizableChartDemo],
};
export const Sunburst = ({ width, height }) => (
export const Sunburst = (
{
showLabels,
showTotal,
}: {
showLabels: boolean;
showTotal: boolean;
},
{ width, height }: { width: number; height: number },
) => (
<SuperChart
chartType="echarts-sunburst"
width={width}
@ -50,8 +58,16 @@ export const Sunburst = ({ width, height }) => (
formData={{
columns: ['genre', 'platform'],
metric: 'count',
showLabels: boolean('Show labels', true),
showTotal: boolean('Show total', true),
showLabels,
showTotal,
}}
/>
);
Sunburst.args = {
showLabels: true,
showTotal: true,
};
Sunburst.argTypes = {
showLabels: { control: 'boolean' },
showTotal: { control: 'boolean' },
};

View File

@ -19,7 +19,6 @@
import React from 'react';
import { SuperChart, getChartTransformPropsRegistry } from '@superset-ui/core';
import { boolean, number, select, withKnobs } from '@storybook/addon-knobs';
import {
EchartsTimeseriesChartPlugin,
TimeseriesTransformProps,
@ -40,12 +39,42 @@ getChartTransformPropsRegistry().registerValue(
);
export default {
title: 'Chart Plugins/plugin-chart-echarts/Timeseries',
decorators: [withKnobs, withResizableChartDemo],
title: 'Chart Plugins/plugin-chart-echarts/SeriesChart',
decorators: [withResizableChartDemo],
};
export const Timeseries = ({ width, height }) => {
const forecastEnabled = boolean('Enable forecast', true);
export const Timeseries = (
{
forecastEnabled,
seriesType,
logAxis,
stack,
showValue,
onlyTotal,
percentageThreshold,
area,
markerEnabled,
markerSize,
minorSplitLine,
opacity,
zoomable,
}: {
forecastEnabled: boolean;
seriesType: string;
logAxis: boolean;
stack: boolean;
showValue: boolean;
onlyTotal: boolean;
percentageThreshold: number;
area: boolean;
markerEnabled: boolean;
markerSize: number;
minorSplitLine: boolean;
opacity: number;
zoomable: boolean;
},
{ width, height }: { width: number; height: number },
) => {
const queryData = data
.map(row =>
forecastEnabled
@ -70,30 +99,74 @@ export const Timeseries = ({ width, height }) => {
formData={{
forecastEnabled,
color_scheme: 'supersetColors',
seriesType: select(
'Line type',
['line', 'scatter', 'smooth', 'bar', 'start', 'middle', 'end'],
'line',
),
logAxis: boolean('Log axis', false),
seriesType,
logAxis,
y_axis_format: 'SMART_NUMBER',
stack: boolean('Stack', false),
show_value: boolean('Show Values', false),
only_total: boolean('Only Total', false),
percentage_threshold: number('Percentage Threshold', 0),
area: boolean('Area chart', false),
markerEnabled: boolean('Enable markers', false),
markerSize: number('Marker Size', 6),
minorSplitLine: boolean('Minor splitline', false),
opacity: number('Opacity', 0.2),
zoomable: boolean('Zoomable', false),
stack,
show_value: showValue,
only_total: onlyTotal,
percentage_threshold: percentageThreshold,
area,
markerEnabled,
markerSize,
minorSplitLine,
opacity,
zoomable,
x_axis: '__timestamp',
}}
/>
);
};
export const WithNegativeNumbers = ({ width, height }) => (
Timeseries.args = {
forecastEnabled: true,
seriesType: 'line',
logAxis: false,
stack: false,
showValue: false,
onlyTotal: false,
percentageThreshold: 0,
area: false,
markerEnabled: false,
markerSize: 6,
minorSplitLine: false,
opacity: 0.2,
zoomable: false,
};
Timeseries.argTypes = {
forecastEnabled: { control: 'boolean' },
seriesType: {
control: 'select',
options: ['line', 'scatter', 'smooth', 'bar', 'start', 'middle', 'end'],
},
logAxis: { control: 'boolean' },
stack: { control: 'boolean' },
showValue: { control: 'boolean' },
onlyTotal: { control: 'boolean' },
percentageThreshold: { control: 'number' },
area: { control: 'boolean' },
markerEnabled: { control: 'boolean' },
markerSize: { control: 'number' },
minorSplitLine: { control: 'boolean' },
opacity: { control: 'number' },
zoomable: { control: 'boolean' },
};
export const WithNegativeNumbers = (
{
seriesType,
stack,
onlyTotal,
orientation,
}: {
seriesType: string;
stack: boolean;
onlyTotal: boolean;
orientation: string;
},
{ width, height }: { width: number; height: number },
) => (
<SuperChart
chartType="echarts-timeseries"
width={width}
@ -103,26 +176,34 @@ export const WithNegativeNumbers = ({ width, height }) => (
]}
formData={{
color_scheme: 'supersetColors',
seriesType: select(
'Line type',
['line', 'scatter', 'smooth', 'bar', 'start', 'middle', 'end'],
'line',
),
seriesType,
y_axis_format: '$,.2f',
stack: boolean('Stack', true),
stack,
show_value: true,
show_legend: true,
only_total: boolean('Only Total', true),
orientation: select(
'Orientation',
['vertical', 'horizontal'],
'vertical',
),
only_total: onlyTotal,
orientation,
x_axis: '__timestamp',
}}
/>
);
WithNegativeNumbers.args = {
seriesType: 'line',
stack: true,
onlyTotal: true,
orientation: 'vertical',
};
WithNegativeNumbers.argTypes = {
seriesType: {
control: 'select',
options: ['line', 'scatter', 'smooth', 'bar', 'start', 'middle', 'end'],
},
stack: { control: 'boolean' },
onlyTotal: { control: 'boolean' },
orientation: { control: 'select', options: ['vertical', 'horizontal'] },
};
export const ConfidenceBand = ({ width, height }) => (
<SuperChart
chartType="echarts-timeseries"

View File

@ -19,7 +19,6 @@
import React from 'react';
import { SuperChart, getChartTransformPropsRegistry } from '@superset-ui/core';
import { select, withKnobs, text, number } from '@storybook/addon-knobs';
import {
EchartsTreeChartPlugin,
TreeTransformProps,
@ -36,10 +35,35 @@ getChartTransformPropsRegistry().registerValue(
export default {
title: 'Chart Plugins/plugin-chart-echarts/Tree',
decorators: [withKnobs, withResizableChartDemo],
decorators: [withResizableChartDemo],
};
export const Tree = ({ width, height }) => (
export const Tree = (
{
id,
rootNodeId,
parent,
name,
position,
layout,
orient,
emphasis,
symbol,
symbolSize,
}: {
id: string;
rootNodeId: string;
parent: string;
name: string;
position: string;
layout: string;
orient: string;
emphasis: string;
symbol: string;
symbolSize: number;
},
{ width, height }: { width: number; height: number },
) => (
<SuperChart
chartType="echarts-tree"
width={width}
@ -50,38 +74,70 @@ export const Tree = ({ width, height }) => (
datasource: '3__table',
granularity_sqla: 'ds',
metric: 'count',
id: select(
'Id Column',
['id_column', 'name_column', 'parent_column'],
'id_column',
),
rootNodeId: text('Root Node', '1'),
parent: select(
'Parent Column',
['parent_column', 'id_column'],
'parent_column',
),
name: select('Name Column', [null, 'name_column'], 'name_column'),
position: select(
'Label Position',
['top', 'right', 'left', 'bottom'],
'top',
),
layout: select('Tree Layout', ['orthogonal', 'radial'], 'orthogonal'),
orient: select('Orientation', ['LR', 'RL', 'TB', 'BT'], 'LR'),
emphasis: select('Emphasis', ['ancestor', 'descendant'], 'descendant'),
symbol: select(
'Symbol',
['emptyCircle', 'circle', 'rect', 'triangle'],
'circle',
),
symbol_size: number('[Symbol Size', 7, {
range: true,
min: 5,
max: 30,
step: 2,
}),
id,
rootNodeId,
parent,
name,
position,
layout,
orient,
emphasis,
symbol,
symbol_size: symbolSize,
}}
/>
);
Tree.args = {
id: 'id_column',
rootNodeId: '1',
parent: 'parent_column',
name: 'name_column',
position: 'top',
layout: 'orthogonal',
orient: 'LR',
emphasis: 'descendant',
symbol: 'circle',
symbolSize: 7,
};
Tree.argTypes = {
id: {
control: 'text',
},
rootNodeId: {
control: 'text',
},
parent: {
control: 'text',
},
name: {
control: 'text',
},
position: {
control: 'select',
options: ['top', 'right', 'left', 'bottom'],
},
layout: {
control: 'select',
options: ['orthogonal', 'radial'],
},
orient: {
control: 'select',
options: ['LR', 'RL', 'TB', 'BT'],
},
emphasis: {
control: 'select',
options: ['ancestor', 'descendant'],
},
symbol: {
control: 'select',
options: ['emptyCircle', 'circle', 'rect', 'triangle'],
},
symbolSize: {
control: 'number',
min: 5,
max: 30,
step: 2,
},
};

View File

@ -19,7 +19,6 @@
import React from 'react';
import { SuperChart, getChartTransformPropsRegistry } from '@superset-ui/core';
import { boolean, withKnobs, select } from '@storybook/addon-knobs';
import {
EchartsTreemapChartPlugin,
TreemapTransformProps,
@ -38,10 +37,21 @@ getChartTransformPropsRegistry().registerValue(
export default {
title: 'Chart Plugins/plugin-chart-echarts/Treemap',
decorators: [withKnobs, withResizableChartDemo],
decorators: [withResizableChartDemo],
};
export const Treemap = ({ width, height }) => (
export const Treemap = (
{
showLabels,
showUpperLabels,
labelType,
}: {
showLabels: boolean;
showUpperLabels: boolean;
labelType: string;
},
{ width, height }: { width: number; height: number },
) => (
<SuperChart
chartType="echarts-treemap"
width={width}
@ -51,13 +61,24 @@ export const Treemap = ({ width, height }) => (
colorScheme: 'supersetColors',
groupby: ['genre'],
metric: 'count',
showLabels: boolean('Show labels', true),
showUpperLabels: boolean('Show upperLabels', true),
labelType: select(
'Treemap label type',
['key', 'value', 'key_value'],
'key_value',
),
showLabels,
showUpperLabels,
labelType,
}}
/>
);
Treemap.args = {
showLabels: true,
showUpperLabels: true,
labelType: 'key_value',
};
Treemap.argTypes = {
showLabels: { control: 'boolean' },
showUpperLabels: { control: 'boolean' },
labelType: {
control: 'select',
options: ['key', 'value', 'key_value'],
},
};

View File

@ -18,7 +18,6 @@
*/
import React from 'react';
import { SuperChart, getChartTransformPropsRegistry } from '@superset-ui/core';
import { withKnobs } from '@storybook/addon-knobs';
import {
EchartsWaterfallChartPlugin,
WaterfallTransformProps,
@ -36,8 +35,8 @@ getChartTransformPropsRegistry().registerValue(
);
export default {
title: 'Chart Plugins|plugin-chart-echarts/Waterfall',
decorators: [withKnobs, withResizableChartDemo],
title: 'Chart Plugins/plugin-chart-echarts/Waterfall',
decorators: [withResizableChartDemo],
};
export const Waterfall = ({ width, height }) => (

View File

@ -18,7 +18,6 @@
*/
import React from 'react';
import { withKnobs } from '@storybook/addon-knobs';
import { SuperChart } from '@superset-ui/core';
import { PivotTableChartPlugin } from '@superset-ui/plugin-chart-pivot-table';
import { basicFormData, basicData } from './testData';
@ -26,12 +25,12 @@ import { withResizableChartDemo } from '../../../shared/components/ResizableChar
export default {
title: 'Chart Plugins/plugin-chart-pivot-table',
decorators: [withKnobs, withResizableChartDemo],
decorators: [withResizableChartDemo],
};
new PivotTableChartPlugin().configure({ key: 'pivot_table_v2' }).register();
export const basic = ({ width, height }) => (
export const Basic = ({ width, height }) => (
<SuperChart
chartType="pivot_table_v2"
datasource={{
@ -43,12 +42,10 @@ export const basic = ({ width, height }) => (
formData={basicFormData}
/>
);
basic.story = {
parameters: {
initialSize: {
width: 680,
height: 420,
},
Basic.parameters = {
initialSize: {
width: 680,
height: 420,
},
};
@ -64,11 +61,9 @@ export const MaximumAggregation = ({ width, height }) => (
formData={{ ...basicFormData, aggregateFunction: 'Maximum' }}
/>
);
basic.story = {
parameters: {
initialSize: {
width: 680,
height: 420,
},
MaximumAggregation.parameters = {
initialSize: {
width: 680,
height: 420,
},
};

View File

@ -19,7 +19,6 @@
import React from 'react';
import memoizeOne from 'memoize-one';
import { withKnobs, number, boolean } from '@storybook/addon-knobs';
import { SuperChart } from '@superset-ui/core';
import TableChartPlugin, {
TableChartProps,
@ -29,7 +28,52 @@ import { withResizableChartDemo } from '../../../shared/components/ResizableChar
export default {
title: 'Chart Plugins/plugin-chart-table',
decorators: [withKnobs, withResizableChartDemo],
decorators: [withResizableChartDemo],
args: {
rows: 2046,
cols: 8,
pageLength: 50,
includeSearch: true,
alignPn: false,
showCellBars: true,
allowRearrangeColumns: false,
},
argTypes: {
rows: {
control: 'number',
name: 'Records',
min: 0,
max: 50000,
},
cols: {
control: 'number',
name: 'Columns',
min: 1,
max: 20,
},
pageLength: {
control: 'number',
name: 'Page size',
min: 0,
max: 100,
},
includeSearch: {
control: 'boolean',
name: 'Include search',
},
alignPn: {
control: 'boolean',
name: 'Align PosNeg',
},
showCellBars: {
control: 'boolean',
name: 'Show Cell Bars',
},
allowRearrangeColumns: {
control: 'boolean',
name: 'Allow end user to drag-and-drop column headers to rearrange them.',
},
},
};
new TableChartPlugin().configure({ key: 'table' }).register();
@ -93,7 +137,7 @@ function loadData(
};
}
export const basic = ({ width, height }) => (
export const Basic = ({ width, height }) => (
<SuperChart
chartType="table"
datasource={{
@ -105,26 +149,33 @@ export const basic = ({ width, height }) => (
formData={basicFormData}
/>
);
basic.story = {
parameters: {
initialSize: {
width: 680,
height: 420,
},
Basic.parameters = {
initialSize: {
width: 680,
height: 420,
},
};
export const BigTable = ({ width, height }) => {
const rows = number('Records', 2046, { range: true, min: 0, max: 50000 });
const cols = number('Columns', 8, { range: true, min: 1, max: 20 });
const pageLength = number('Page size', 50, { range: true, min: 0, max: 100 });
const includeSearch = boolean('Include search', true);
const alignPn = boolean('Align PosNeg', false);
const showCellBars = boolean('Show Cell Bars', true);
const allowRearrangeColumns = boolean(
'Allow end user to drag-and-drop column headers to rearrange them.',
false,
);
export const BigTable = (
{
rows,
cols,
pageLength,
includeSearch,
alignPn,
showCellBars,
allowRearrangeColumns,
}: {
rows: number;
cols: number;
pageLength: number;
includeSearch: boolean;
alignPn: boolean;
showCellBars: boolean;
allowRearrangeColumns: boolean;
},
{ width, height }: { width: number; height: number },
) => {
const chartProps = loadData(birthNames, {
pageLength,
rows,
@ -143,11 +194,9 @@ export const BigTable = ({ width, height }) => {
/>
);
};
BigTable.story = {
parameters: {
initialSize: {
width: 620,
height: 440,
},
BigTable.parameters = {
initialSize: {
width: 620,
height: 440,
},
};

View File

@ -19,7 +19,6 @@
import React from 'react';
import { SuperChart, getChartTransformPropsRegistry } from '@superset-ui/core';
import { select, withKnobs } from '@storybook/addon-knobs';
import {
WordCloudChartPlugin,
LegacyWordCloudChartPlugin,
@ -42,10 +41,26 @@ getChartTransformPropsRegistry().registerValue(
export default {
title: 'Chart Plugins/plugin-chart-word-cloud',
decorators: [withKnobs, withResizableChartDemo],
decorators: [withResizableChartDemo],
args: {
rotation: 'flat',
},
argTypes: {
rotation: {
control: 'select',
options: ['square', 'flat', 'random'],
},
},
};
export const basic = ({ width, height }) => (
export const basic = (
{
rotation,
}: {
rotation: string;
},
{ width, height }: { width: number; height: number },
) => (
<SuperChart
chartType="word-cloud2"
width={width}
@ -69,13 +84,20 @@ export const basic = ({ width, height }) => (
},
},
metric: 'sum__num',
rotation: select('Rotation', ['square', 'flat', 'random'], 'flat'),
rotation,
series: 'name',
}}
/>
);
export const encodesColorByWordLength = ({ width, height }) => (
export const encodesColorByWordLength = (
{
rotation,
}: {
rotation: string;
},
{ width, height }: { width: number; height: number },
) => (
<SuperChart
chartType="word-cloud2"
width={width}
@ -105,13 +127,20 @@ export const encodesColorByWordLength = ({ width, height }) => (
},
},
metric: 'sum__num',
rotation: select('Rotation', ['square', 'flat', 'random'], 'flat'),
rotation,
series: 'name',
}}
/>
);
export const encodesFontByFirstLetter = ({ width, height }) => (
export const encodesFontByFirstLetter = (
{
rotation,
}: {
rotation: string;
},
{ width, height }: { width: number; height: number },
) => (
<SuperChart
chartType="word-cloud2"
width={width}
@ -143,13 +172,20 @@ export const encodesFontByFirstLetter = ({ width, height }) => (
},
},
metric: 'sum__num',
rotation: select('Rotation', ['square', 'flat', 'random'], 'flat'),
rotation,
series: 'name',
}}
/>
);
export const legacyShim = ({ width, height }) => (
export const legacyShim = (
{
rotation,
}: {
rotation: string;
},
{ width, height }: { width: number; height: number },
) => (
<SuperChart
chartType="legacy-word-cloud2"
width={width}
@ -158,7 +194,7 @@ export const legacyShim = ({ width, height }) => (
formData={{
colorScheme: 'd3Category10',
metric: 'sum__num',
rotation: select('Rotation', ['square', 'flat', 'random'], 'flat'),
rotation,
series: 'name',
sizeFrom: '10',
sizeTo: '70',

View File

@ -18,7 +18,6 @@
*/
import React from 'react';
import { text, select, withKnobs } from '@storybook/addon-knobs';
import {
SuperChart,
@ -62,64 +61,83 @@ const FORM_DATA_LOOKUP = {
export default {
title: 'Others/DataProvider',
decorators: [
withKnobs({
escapeHTML: false,
}),
],
decorators: [],
};
export const dataProvider = () => {
const host = text('Set Superset App host for CORS request', 'localhost:8088');
const visType = select('Chart Plugin Type', VIS_TYPES, VIS_TYPES[0]);
const width = text('Vis width', '500');
const height = text('Vis height', '300');
const formData = text(
'Override formData',
JSON.stringify(FORM_DATA_LOOKUP[visType]),
);
export const dataProvider = ({
host,
visType,
width,
height,
formData,
}: {
host: string;
visType: string;
width: number;
height: number;
formData: string;
}) => (
<div style={{ margin: 16 }}>
<VerifyCORS host={host}>
{() => (
<ChartDataProvider
client={SupersetClient}
formData={JSON.parse(formData)}
>
{({ loading, payload, error }) => {
if (loading) return <div>Loading!</div>;
return (
<div style={{ margin: 16 }}>
<VerifyCORS host={host}>
{() => (
<ChartDataProvider
client={SupersetClient}
formData={JSON.parse(formData)}
>
{({ loading, payload, error }) => {
if (loading) return <div>Loading!</div>;
if (error) return renderError(error);
if (error) return renderError(error);
if (payload)
return (
<>
<SuperChart
chartType={visType}
formData={payload.formData}
height={Number(height)}
// @TODO fix typing
// all vis's now expect objects but api/v1/ returns an array
queriesData={payload.queriesData}
width={Number(width)}
/>
<br />
<Expandable expandableWhat="payload">
<pre style={{ fontSize: 11 }}>
{JSON.stringify(payload, null, 2)}
</pre>
</Expandable>
</>
);
if (payload)
return (
<>
<SuperChart
chartType={visType}
formData={payload.formData}
height={Number(height)}
// @TODO fix typing
// all vis's now expect objects but api/v1/ returns an array
queriesData={payload.queriesData}
width={Number(width)}
/>
<br />
<Expandable expandableWhat="payload">
<pre style={{ fontSize: 11 }}>
{JSON.stringify(payload, null, 2)}
</pre>
</Expandable>
</>
);
return null;
}}
</ChartDataProvider>
)}
</VerifyCORS>
</div>
);
return null;
}}
</ChartDataProvider>
)}
</VerifyCORS>
</div>
);
dataProvider.storyName = 'ChartDataProvider';
dataProvider.args = {
host: 'localhost:8088',
visType: VIS_TYPES[0],
width: '500',
height: '300',
formData: JSON.stringify(FORM_DATA_LOOKUP[VIS_TYPES[0]]),
};
dataProvider.argTypes = {
host: {
control: 'text',
description: 'Set Superset App host for CORS request',
},
visType: {
control: 'select',
options: VIS_TYPES,
description: 'Chart Plugin Type',
},
width: { control: 'text', description: 'Vis width' },
height: { control: 'text', description: 'Vis height' },
formData: { control: 'text', description: 'Override formData' },
};
dataProvider.story = { name: 'ChartDataProvider' };

View File

@ -0,0 +1,255 @@
/*
* 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 { SuperChart } from '@superset-ui/core';
import {
DiligentChartPlugin,
BuggyChartPlugin,
ChartKeys,
} from '../../../../superset-ui-core/test/chart/components/MockChartPlugins';
import ResizableChartDemo from '../../shared/components/ResizableChartDemo';
new DiligentChartPlugin().configure({ key: ChartKeys.DILIGENT }).register();
new BuggyChartPlugin().configure({ key: ChartKeys.BUGGY }).register();
const DEFAULT_QUERY_DATA = { data: ['foo', 'bar'] };
export default {
title: 'Others/SuperChart',
decorators: [],
};
export const basic = ({ width, height }: { width: string; height: string }) => (
<SuperChart
chartType={ChartKeys.DILIGENT}
width={width}
height={height}
queriesData={[DEFAULT_QUERY_DATA]}
formData={{ hi: 1 }}
/>
);
basic.args = {
width: '100%',
height: '100%',
};
basic.argTypes = {
width: { control: 'text', description: 'Vis width' },
height: { control: 'text', description: 'Vis height' },
};
export const container50pct = ({
width,
height,
}: {
width: string;
height: string;
}) => (
<SuperChart
chartType={ChartKeys.DILIGENT}
width={width}
height={height}
queriesData={[DEFAULT_QUERY_DATA]}
formData={{ hi: 1 }}
/>
);
container50pct.storyName = '50% of container';
container50pct.args = {
width: '50%',
height: '50%',
};
container50pct.argTypes = {
width: { control: 'text', description: 'Vis width' },
height: { control: 'text', description: 'Vis height' },
};
export const Resizable = () => (
<ResizableChartDemo>
{size => (
<SuperChart
chartType={ChartKeys.DILIGENT}
width={size.width}
height={size.height}
queriesData={[DEFAULT_QUERY_DATA]}
/>
)}
</ResizableChartDemo>
);
export const fixedWidth100height = ({
width,
height,
}: {
width: string;
height: string;
}) => (
<SuperChart
chartType={ChartKeys.DILIGENT}
height={height}
width={width}
queriesData={[DEFAULT_QUERY_DATA]}
/>
);
fixedWidth100height.storyName = 'fixed width, 100% height';
fixedWidth100height.args = {
width: '500',
height: '100%',
};
fixedWidth100height.argTypes = {
width: { control: 'text', description: 'Vis width' },
height: { control: 'text', description: 'Vis height' },
};
export const fixedHeight100Width = ({
width,
height,
}: {
width: string;
height: string;
}) => (
<SuperChart
chartType={ChartKeys.DILIGENT}
height={height}
width={width}
queriesData={[DEFAULT_QUERY_DATA]}
/>
);
fixedHeight100Width.storyName = 'fixed height, 100% width';
fixedHeight100Width.args = {
width: '100%',
height: '300',
};
fixedHeight100Width.argTypes = {
width: { control: 'text', description: 'Vis width' },
height: { control: 'text', description: 'Vis height' },
};
export const withErrorBoundary = ({
width,
height,
}: {
width: string;
height: string;
}) => (
<SuperChart
chartType={ChartKeys.BUGGY}
height={height}
width={width}
queriesData={[DEFAULT_QUERY_DATA]}
/>
);
withErrorBoundary.storyName = 'With Error Boundary';
withErrorBoundary.args = {
width: '500',
height: '300',
};
withErrorBoundary.argTypes = {
width: { control: 'text', description: 'Vis width' },
height: { control: 'text', description: 'Vis height' },
};
export const withWrapper = ({
width,
height,
}: {
width: string;
height: string;
}) => (
<SuperChart
chartType={ChartKeys.DILIGENT}
width={width}
height={height}
queriesData={[DEFAULT_QUERY_DATA]}
Wrapper={({ children }) => (
<div>
<div style={{ margin: 10, position: 'fixed' }}>With wrapper!</div>
{children}
</div>
)}
/>
);
withWrapper.storyName = 'With Wrapper';
withWrapper.args = {
width: '100%',
height: '100%',
};
withWrapper.argTypes = {
width: { control: 'text', description: 'Vis width' },
height: { control: 'text', description: 'Vis height' },
};
export const withNoResults = ({
width,
height,
}: {
width: string;
height: string;
}) => (
<SuperChart chartType={ChartKeys.DILIGENT} width={width} height={height} />
);
withNoResults.storyName = 'With no results';
withNoResults.args = {
width: '100%',
height: '100%',
};
withNoResults.argTypes = {
width: { control: 'text', description: 'Vis width' },
height: { control: 'text', description: 'Vis height' },
};
export const withNoResultsAndMedium = ({
width,
height,
}: {
width: string;
height: string;
}) => (
<SuperChart chartType={ChartKeys.DILIGENT} width={width} height={height} />
);
withNoResultsAndMedium.storyName = 'With no results and medium';
withNoResultsAndMedium.args = {
width: '400',
height: '300',
};
withNoResultsAndMedium.argTypes = {
width: { control: 'text', description: 'Vis width' },
height: { control: 'text', description: 'Vis height' },
};
export const withNoResultsAndSmall = ({
width,
height,
}: {
width: string;
height: string;
}) => (
<SuperChart chartType={ChartKeys.DILIGENT} width={width} height={height} />
);
withNoResultsAndSmall.storyName = 'With no results and small';
withNoResultsAndSmall.args = {
width: '150',
height: '200',
};
withNoResultsAndSmall.argTypes = {
width: { control: 'text', description: 'Vis width' },
height: { control: 'text', description: 'Vis height' },
};

View File

@ -1,169 +0,0 @@
/*
* 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 { text, withKnobs } from '@storybook/addon-knobs';
import { SuperChart } from '@superset-ui/core';
import {
DiligentChartPlugin,
BuggyChartPlugin,
ChartKeys,
} from '../../../../superset-ui-core/test/chart/components/MockChartPlugins';
import ResizableChartDemo from '../../shared/components/ResizableChartDemo';
new DiligentChartPlugin().configure({ key: ChartKeys.DILIGENT }).register();
new BuggyChartPlugin().configure({ key: ChartKeys.BUGGY }).register();
const DEFAULT_QUERY_DATA = { data: ['foo', 'bar'] };
export default {
title: 'Others/SuperChart',
decorators: [withKnobs],
};
export const basic = () => {
const width = text('Vis width', '100%');
const height = text('Vis height', '100%');
return (
<SuperChart
chartType={ChartKeys.DILIGENT}
width={width}
height={height}
queriesData={[DEFAULT_QUERY_DATA]}
formData={{ hi: 1 }}
/>
);
};
export const container50pct = () => {
const width = text('Vis width', '50%');
const height = text('Vis height', '50%');
return (
<SuperChart
chartType={ChartKeys.DILIGENT}
width={width}
height={height}
queriesData={[DEFAULT_QUERY_DATA]}
formData={{ hi: 1 }}
/>
);
};
container50pct.story = { name: '50% of container' };
export const Resizable = () => (
<ResizableChartDemo>
{size => (
<SuperChart
chartType={ChartKeys.DILIGENT}
width={size.width}
height={size.height}
queriesData={[DEFAULT_QUERY_DATA]}
/>
)}
</ResizableChartDemo>
);
export const fixedWidth100height = () => {
const width = text('Vis width', '500');
const height = text('Vis height', '100%');
return (
<SuperChart
chartType={ChartKeys.DILIGENT}
height={height}
width={width}
queriesData={[DEFAULT_QUERY_DATA]}
/>
);
};
fixedWidth100height.story = { name: 'fixed width, 100% height' };
export const fixedHeight100Width = () => {
const width = text('Vis width', '100%');
const height = text('Vis height', '300');
return (
<SuperChart
chartType={ChartKeys.DILIGENT}
height={height}
width={width}
queriesData={[DEFAULT_QUERY_DATA]}
/>
);
};
fixedHeight100Width.story = { name: 'fixed height, 100% width' };
export const withErrorBoundary = () => {
const width = text('Vis width', '500');
const height = text('Vis height', '300');
return (
<SuperChart
chartType={ChartKeys.BUGGY}
height={height}
width={width}
queriesData={[DEFAULT_QUERY_DATA]}
/>
);
};
export const withWrapper = () => {
const width = text('Vis width', '100%');
const height = text('Vis height', '100%');
return (
<SuperChart
chartType={ChartKeys.DILIGENT}
width={width}
height={height}
queriesData={[DEFAULT_QUERY_DATA]}
Wrapper={({ children }) => (
<div>
<div style={{ margin: 10, position: 'fixed' }}>With wrapper!</div>
{children}
</div>
)}
/>
);
};
export const withNoResults = () => {
const width = text('Vis width', '100%');
const height = text('Vis height', '100%');
return (
<SuperChart chartType={ChartKeys.DILIGENT} width={width} height={height} />
);
};
export const withNoResultsAndMedium = () => {
const width = text('Vis width', '400');
const height = text('Vis height', '300');
return (
<SuperChart chartType={ChartKeys.DILIGENT} width={width} height={height} />
);
};
export const withNoResultsAndSmall = () => {
const width = text('Vis width', '150');
const height = text('Vis height', '200');
return (
<SuperChart chartType={ChartKeys.DILIGENT} width={width} height={height} />
);
};

View File

@ -18,7 +18,6 @@
*/
import React from 'react';
import { select, text, withKnobs } from '@storybook/addon-knobs';
import { bigNumberFormData } from '../../../../superset-ui-core/test/chart/fixtures/formData';
import VerifyCORS, {
@ -35,24 +34,29 @@ const ENDPOINTS = {
export default {
title: 'Core Packages/@superset-ui-connection',
decorators: [
withKnobs({
escapeHTML: false,
}),
// withKnobs({
// escapeHTML: false,
// }),
],
};
export const configureCORS = () => {
const host = text('Superset App host for CORS request', 'localhost:8088');
const selectEndpoint = select('Endpoint', ENDPOINTS, '');
const customEndpoint = text('Custom Endpoint (override above)', '');
export const configureCORS = ({
host,
selectEndpoint,
customEndpoint,
methodOption,
postPayloadContents,
}: {
host: string;
selectEndpoint: string;
customEndpoint: string;
methodOption: string;
postPayloadContents: string;
}) => {
const endpoint = customEndpoint || selectEndpoint;
const method = endpoint
? select('Request method', REQUEST_METHODS, 'POST')
: undefined;
const method = endpoint ? methodOption : undefined;
const postPayload =
endpoint && method === 'POST'
? text('POST payload', JSON.stringify({ form_data: bigNumberFormData }))
: undefined;
endpoint && method === 'POST' ? postPayloadContents : undefined;
return (
<div style={{ margin: 16 }}>
@ -65,7 +69,7 @@ export const configureCORS = () => {
{({ payload }) => (
<>
<div className="alert alert-success">
Success! Update knobs below to try again
Success! Update controls below to try again
</div>
<br />
<Expandable expandableWhat="payload">
@ -84,3 +88,38 @@ export const configureCORS = () => {
configureCORS.parameters = {
chromatic: { disable: true },
};
configureCORS.args = {
host: 'localhost:8088',
selectEndpoint: '/api/v1/chart/data',
customEndpoint: '',
methodOption: 'POST', // TODO disable when custonEndpoint and selectEndpoint are empty
postPayloadContents: JSON.stringify({ form_data: bigNumberFormData }),
};
configureCORS.argTypes = {
host: {
control: 'text',
description: 'Set Superset App host for CORS request',
},
selectEndpoint: {
control: {
type: 'select',
options: Object.keys(ENDPOINTS),
},
mapping: ENDPOINTS,
description: 'Select an endpoint',
},
customEndpoint: {
control: 'text',
description: 'Custom Endpoint (override above)',
},
methodOption: {
control: 'select',
options: REQUEST_METHODS,
description: 'Select a request method',
},
postPayloadContents: {
control: 'text',
description: 'Set POST payload contents',
},
};
configureCORS.storyName = 'Verify CORS';

View File

@ -234,16 +234,19 @@ export default function transformProps(
const formatter = contributionMode
? getNumberFormatter(',.0%')
: currencyFormat?.symbol
? new CurrencyFormatter({ d3Format: yAxisFormat, currency: currencyFormat })
: getNumberFormatter(yAxisFormat);
? new CurrencyFormatter({
d3Format: yAxisFormat,
currency: currencyFormat,
})
: getNumberFormatter(yAxisFormat);
const formatterSecondary = contributionMode
? getNumberFormatter(',.0%')
: currencyFormatSecondary?.symbol
? new CurrencyFormatter({
d3Format: yAxisFormatSecondary,
currency: currencyFormatSecondary,
})
: getNumberFormatter(yAxisFormatSecondary);
? new CurrencyFormatter({
d3Format: yAxisFormatSecondary,
currency: currencyFormatSecondary,
})
: getNumberFormatter(yAxisFormatSecondary);
const customFormatters = buildCustomFormatters(
[...ensureIsArray(metrics), ...ensureIsArray(metricsB)],
currencyFormats,
@ -369,7 +372,7 @@ export default function transformProps(
customFormatters,
formatter,
metrics,
labelMap[seriesName]?.[0],
labelMap?.[seriesName]?.[0],
!!contributionMode,
);
@ -414,7 +417,7 @@ export default function transformProps(
customFormattersSecondary,
formatterSecondary,
metricsB,
labelMapB[seriesName]?.[0],
labelMapB?.[seriesName]?.[0],
!!contributionMode,
);

View File

@ -21,21 +21,34 @@ import {
sections,
} from '@superset-ui/chart-controls';
import { t } from '@superset-ui/core';
import { LegendOrientation, LegendType } from '../types';
import {
OrientationType,
EchartsTimeseriesSeriesType,
EchartsTimeseriesFormData,
} from './types';
import {
DEFAULT_LEGEND_FORM_DATA,
DEFAULT_TITLE_FORM_DATA,
} from '../constants';
// import {
// DEFAULT_LEGEND_FORM_DATA,
// DEFAULT_TITLE_FORM_DATA,
// } from '../constants';
import { defaultXAxis } from '../defaults';
// @ts-ignore
export const DEFAULT_FORM_DATA: EchartsTimeseriesFormData = {
...DEFAULT_LEGEND_FORM_DATA,
...DEFAULT_TITLE_FORM_DATA,
// ...DEFAULT_LEGEND_FORM_DATA, // TODO: figure out why these break things for stories (e.g. Bubble Chart)
// Here are the contents of DEFAULT_LEGEND_FORM_DATA:
legendMargin: null,
legendOrientation: LegendOrientation.Top,
legendType: LegendType.Scroll,
showLegend: true,
// ...DEFAULT_TITLE_FORM_DATA, // TODO: figure out why these break things for stories (e.g. Bubble Chart)
// here are the contents of DEFAULT_TITLE_FORM_DATA:
xAxisTitle: '',
xAxisTitleMargin: 0,
yAxisTitle: '',
yAxisTitleMargin: 0,
yAxisTitlePosition: 'Top',
// Now that the weird bug workaround is over, here's the rest...
...DEFAULT_SORT_SERIES_DATA,
annotationLayers: sections.annotationLayers,
area: false,

View File

@ -219,7 +219,7 @@ export default function transformProps(
getMetricLabel,
);
const isMultiSeries = groupby.length || metrics.length > 1;
const isMultiSeries = groupby?.length || metrics?.length > 1;
const [rawSeries, sortedTotalValues, minPositiveValue] = extractSeries(
rebasedData,
@ -297,7 +297,7 @@ export default function transformProps(
: getCustomFormatter(
customFormatters,
metrics,
labelMap[seriesName]?.[0],
labelMap?.[seriesName]?.[0],
) ?? defaultFormatter,
showValue,
onlyTotal,

View File

@ -187,9 +187,9 @@ export default function transformProps(
currencyFormat,
granularitySqla = '',
groupby,
increaseColor,
decreaseColor,
totalColor,
increaseColor = { r: 90, g: 193, b: 137 },
decreaseColor = { r: 224, g: 67, b: 85 },
totalColor = { r: 102, g: 102, b: 102 },
metric = '',
xAxis,
xTicksLayout,

View File

@ -45,12 +45,15 @@ export const extractForecastSeriesContext = (
export const extractForecastSeriesContexts = (
seriesNames: string[],
): { [key: string]: ForecastSeriesEnum[] } =>
seriesNames.reduce((agg, name) => {
const context = extractForecastSeriesContext(name);
const currentContexts = agg[context.name] || [];
currentContexts.push(context.type);
return { ...agg, [context.name]: currentContexts };
}, {} as { [key: string]: ForecastSeriesEnum[] });
seriesNames.reduce(
(agg, name) => {
const context = extractForecastSeriesContext(name);
const currentContexts = agg[context.name] || [];
currentContexts.push(context.type);
return { ...agg, [context.name]: currentContexts };
},
{} as { [key: string]: ForecastSeriesEnum[] },
);
export const extractForecastValuesFromTooltipParams = (
params: any[],

View File

@ -186,7 +186,8 @@ const usFmtPct = numberFormat({
suffix: '%',
});
const fmtNonString = formatter => x => typeof x === 'string' ? x : formatter(x);
const fmtNonString = formatter => x =>
typeof x === 'string' ? x : formatter(x);
const baseAggregatorTemplates = {
count(formatter = usFmtInt) {

View File

@ -361,8 +361,8 @@ export default function TableChart<D extends DataRecord = DataRecord>(
const textAlign = config.horizontalAlign
? config.horizontalAlign
: isNumeric
? 'right'
: 'left';
? 'right'
: 'left';
return {
textAlign,
};

View File

@ -184,8 +184,7 @@ const processColumns = memoizeOne(function processColumns(
typeof percentMetrics,
typeof columns,
];
},
isEqualColumns);
}, isEqualColumns);
/**
* Automatically set page size based on number of cells.

View File

@ -66,11 +66,11 @@ export function formatColumnValue(
config.d3SmallNumberFormat === undefined
? formatter
: config.currencyFormat
? new CurrencyFormatter({
d3Format: config.d3SmallNumberFormat,
currency: config.currencyFormat,
})
: getNumberFormatter(config.d3SmallNumberFormat);
? new CurrencyFormatter({
d3Format: config.d3SmallNumberFormat,
currency: config.currencyFormat,
})
: getNumberFormatter(config.d3SmallNumberFormat);
return formatValue(
isNumber && typeof value === 'number' && Math.abs(value) < 1
? smallNumberFormatter

View File

@ -51,7 +51,9 @@ const StyledAceEditor = styled(AceEditor)`
&& {
// double class is better than !important
border: 1px solid ${theme.colors.grayscale.light2};
font-feature-settings: 'liga' off, 'calt' off;
font-feature-settings:
'liga' off,
'calt' off;
&.ace_autocomplete {
// Use !important because Ace Editor applies extra CSS at the last second

Some files were not shown because too many files have changed in this diff Show More