docs: add path demo

This commit is contained in:
Krist Wongsuphasawat 2019-09-18 18:15:07 -07:00 committed by Yongjie Zhao
parent fd6b2b6ebe
commit 5d5e68bdf5
62 changed files with 275 additions and 3183 deletions

View File

@ -1,43 +0,0 @@
## @superset-ui/legacy-preset-chart-nvd3
[![Version](https://img.shields.io/npm/v/@superset-ui/legacy-preset-chart-nvd3.svg?style=flat-square)](https://img.shields.io/npm/v/@superset-ui/legacy-preset-chart-nvd3.svg?style=flat-square)
[![David (path)](https://img.shields.io/david/apache-superset/superset-ui-plugins.svg?path=packages%2Fsuperset-ui-legacy-preset-chart-nvd3&style=flat-square)](https://david-dm.org/apache-superset/superset-ui-plugins?path=packages/superset-ui-legacy-preset-chart-nvd3)
This plugin provides Big Number for Superset.
### Usage
Import the preset and register. This will register all the chart plugins under nvd3.
```js
import { NVD3ChartPreset } from '@superset-ui/legacy-preset-chart-nvd3';
new NVD3ChartPreset().register();
```
or register charts one by one. Configure `key`, which can be any `string`, and register the plugin. This `key` will be used to lookup this chart throughout the app.
```js
import { AreaChartPlugin, LineChartPlugin } from '@superset-ui/legacy-preset-chart-nvd3';
new AreaChartPlugin()
.configure({ key: 'area' })
.register();
new LineChartPlugin()
.configure({ key: 'line' })
.register();
```
Then use it via `SuperChart`. See [storybook](https://apache-superset.github.io/superset-ui-plugins/?selectedKind=plugin-chart-nvd3) for more details.
```js
<SuperChart
chartType="line"
width={600}
height={600}
formData={...}
queryData={{
data: {...},
}}
/>
```

View File

@ -1,54 +0,0 @@
{
"name": "@superset-ui/legacy-preset-chart-nvd3",
"version": "0.11.0",
"description": "Superset Legacy Chart - NVD3",
"sideEffects": [
"*.css"
],
"main": "lib/index.js",
"module": "esm/index.js",
"files": [
"esm",
"lib"
],
"repository": {
"type": "git",
"url": "git+https://github.com/apache-superset/superset-ui-plugins.git"
},
"keywords": [
"superset"
],
"author": "Superset",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/apache-superset/superset-ui-plugins/issues"
},
"homepage": "https://github.com/apache-superset/superset-ui-plugins#readme",
"publishConfig": {
"access": "public"
},
"private": true,
"dependencies": {
"@data-ui/xy-chart": "^0.0.80",
"d3": "^3.5.17",
"d3-tip": "^0.9.1",
"dompurify": "^1.0.3",
"fast-safe-stringify": "^2.0.6",
"lodash": "^4.17.11",
"mathjs": "^3.20.2",
"moment": "^2.20.1",
"nvd3": "1.8.6",
"prop-types": "^15.6.2",
"urijs": "^1.18.10"
},
"peerDependencies": {
"@superset-ui/chart": "^0.12.0",
"@superset-ui/color": "^0.12.0",
"@superset-ui/core": "^0.12.0",
"@superset-ui/dimension": "^0.12.0",
"@superset-ui/number-format": "^0.12.0",
"@superset-ui/time-format": "^0.12.0",
"@superset-ui/translation": "^0.12.0",
"react": "^15 || ^16"
}
}

View File

@ -1,42 +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 { t } from '@superset-ui/translation';
import { ChartMetadata, ChartPlugin } from '@superset-ui/chart';
import transformProps from '../transformProps';
import thumbnail from './images/thumbnail.png';
import { ANNOTATION_TYPES } from '../vendor/superset/AnnotationTypes';
const metadata = new ChartMetadata({
credits: ['http://nvd3.org'],
description: '',
name: t('Area Chart'),
supportedAnnotationTypes: [ANNOTATION_TYPES.INTERVAL, ANNOTATION_TYPES.EVENT],
thumbnail,
useLegacyApi: true,
});
export default class AreaChartPlugin extends ChartPlugin {
constructor() {
super({
loadChart: () => import('../ReactNVD3'),
metadata,
transformProps,
});
}
}

View File

@ -1,42 +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 { t } from '@superset-ui/translation';
import { ChartMetadata, ChartPlugin } from '@superset-ui/chart';
import transformProps from '../transformProps';
import thumbnail from './images/thumbnail.png';
import { ANNOTATION_TYPES } from '../vendor/superset/AnnotationTypes';
const metadata = new ChartMetadata({
credits: ['http://nvd3.org'],
description: 'A bar chart where the x axis is time',
name: t('Time-series Bar Chart'),
supportedAnnotationTypes: [ANNOTATION_TYPES.INTERVAL, ANNOTATION_TYPES.EVENT],
thumbnail,
useLegacyApi: true,
});
export default class BarChartPlugin extends ChartPlugin {
constructor() {
super({
loadChart: () => import('../ReactNVD3'),
metadata,
transformProps,
});
}
}

View File

@ -1,40 +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 { t } from '@superset-ui/translation';
import { ChartMetadata, ChartPlugin } from '@superset-ui/chart';
import transformProps from '../transformProps';
import thumbnail from './images/thumbnail.png';
const metadata = new ChartMetadata({
credits: ['http://nvd3.org'],
description: '',
name: t('Box Plot'),
thumbnail,
useLegacyApi: true,
});
export default class BoxPlotChartPlugin extends ChartPlugin {
constructor() {
super({
loadChart: () => import('../ReactNVD3'),
metadata,
transformProps,
});
}
}

View File

@ -1,40 +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 { t } from '@superset-ui/translation';
import { ChartMetadata, ChartPlugin } from '@superset-ui/chart';
import transformProps from '../transformProps';
import thumbnail from './images/thumbnail.png';
const metadata = new ChartMetadata({
credits: ['http://nvd3.org'],
description: '',
name: t('Bubble Chart'),
thumbnail,
useLegacyApi: true,
});
export default class BubbleChartPlugin extends ChartPlugin {
constructor() {
super({
loadChart: () => import('../ReactNVD3'),
metadata,
transformProps,
});
}
}

View File

@ -1,40 +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 { t } from '@superset-ui/translation';
import { ChartMetadata, ChartPlugin } from '@superset-ui/chart';
import transformProps from '../transformProps';
import thumbnail from './images/thumbnail.png';
const metadata = new ChartMetadata({
credits: ['http://nvd3.org'],
description: '',
name: t('Bullet Chart'),
thumbnail,
useLegacyApi: true,
});
export default class BulletChartPlugin extends ChartPlugin {
constructor() {
super({
loadChart: () => import('../ReactNVD3'),
metadata,
transformProps,
});
}
}

View File

@ -1,40 +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 { t } from '@superset-ui/translation';
import { ChartMetadata, ChartPlugin } from '@superset-ui/chart';
import transformProps from '../transformProps';
import thumbnail from './images/thumbnail.png';
const metadata = new ChartMetadata({
credits: ['http://nvd3.org'],
description: t('A line chart component where you can compare the % change over time'),
name: t('Time-series Percent Change'),
thumbnail,
useLegacyApi: true,
});
export default class CompareChartPlugin extends ChartPlugin {
constructor() {
super({
loadChart: () => import('../ReactNVD3'),
metadata,
transformProps,
});
}
}

View File

@ -1,40 +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 { t } from '@superset-ui/translation';
import { ChartMetadata, ChartPlugin } from '@superset-ui/chart';
import transformProps from '../transformProps';
import thumbnail from './images/thumbnail.png';
const metadata = new ChartMetadata({
credits: ['http://nvd3.org'],
description: t('A bar chart where the x axis is time'),
name: t('Bar Chart'),
thumbnail,
useLegacyApi: true,
});
export default class DistBarChartPlugin extends ChartPlugin {
constructor() {
super({
loadChart: () => import('../ReactNVD3'),
metadata,
transformProps,
});
}
}

View File

@ -1,40 +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 { t } from '@superset-ui/translation';
import { ChartMetadata, ChartPlugin } from '@superset-ui/chart';
import transformProps from '../transformProps';
import thumbnail from './images/thumbnail.png';
const metadata = new ChartMetadata({
credits: ['http://nvd3.org'],
description: '',
name: t('Dual Line Chart'),
thumbnail,
useLegacyApi: true,
});
export default class DualLineChartPlugin extends ChartPlugin {
constructor() {
super({
loadChart: () => import('../ReactNVD3'),
metadata,
transformProps,
});
}
}

View File

@ -1,48 +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 { t } from '@superset-ui/translation';
import { ChartMetadata, ChartPlugin } from '@superset-ui/chart';
import transformProps from '../transformProps';
import thumbnail from './images/thumbnail.png';
import { ANNOTATION_TYPES } from '../vendor/superset/AnnotationTypes';
const metadata = new ChartMetadata({
canBeAnnotationTypes: [ANNOTATION_TYPES.TIME_SERIES],
credits: ['http://nvd3.org'],
description: '',
name: t('Line Chart'),
supportedAnnotationTypes: [
ANNOTATION_TYPES.TIME_SERIES,
ANNOTATION_TYPES.INTERVAL,
ANNOTATION_TYPES.EVENT,
ANNOTATION_TYPES.FORMULA,
],
thumbnail,
useLegacyApi: true,
});
export default class LineChartPlugin extends ChartPlugin {
constructor() {
super({
loadChart: () => import('../ReactNVD3'),
metadata,
transformProps,
});
}
}

View File

@ -1,170 +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.
*/
/* eslint-disable sort-keys, react/require-default-props, react/forbid-prop-types */
/* eslint-disable promise/always-return, promise/catch-or-return */
import d3 from 'd3';
import React from 'react';
import PropTypes from 'prop-types';
import { getExploreLongUrl } from '../vendor/superset/exploreUtils';
import ReactNVD3 from '../ReactNVD3';
import transformProps from '../transformProps';
const propTypes = {
width: PropTypes.number,
height: PropTypes.number,
annotationData: PropTypes.object,
datasource: PropTypes.object,
formData: PropTypes.object,
onAddFilter: PropTypes.func,
onError: PropTypes.func,
};
const defaultProps = {
onAddFilter() {},
onError() {},
};
function getJson(url) {
return new Promise((resolve, reject) => {
d3.json(url, (error, response) => {
if (error) {
reject(error);
} else {
resolve(response.data);
}
});
});
}
/*
* Show multiple line charts
*
* This visualization works by fetching the data from each of the saved
* charts, building the queryData data and passing it along to nvd3Vis.
*/
class LineMulti extends React.Component {
constructor(props) {
super(props);
this.state = { queryData: [] };
}
componentDidMount() {
this.loadData(this.props);
}
componentWillReceiveProps(nextProps) {
this.loadData(nextProps);
}
loadData(props) {
const { formData, queryData } = props;
const { slices } = queryData.data;
const {
extraFilters,
filters,
lineCharts,
lineCharts2,
prefixMetricWithSliceName,
timeRange,
} = formData;
this.setState({ queryData: [] });
// fetch data from all the charts
const subslices = [
...slices.axis1.map(subslice => [1, subslice]),
...slices.axis2.map(subslice => [2, subslice]),
];
const promises = subslices.map(([yAxis, subslice]) => {
const subsliceFormData = subslice.form_data;
const combinedFormData = {
...subslice.form_data,
extra_filters: extraFilters || [],
filters: (subsliceFormData.filters || []).concat(filters || []),
time_range: timeRange,
};
const addPrefix = prefixMetricWithSliceName;
return getJson(getExploreLongUrl(combinedFormData, 'json')).then(data =>
data.map(({ key, values }) => ({
key: addPrefix ? `${subslice.slice_name}: ${key}` : key,
type: combinedFormData.viz_type,
values,
yAxis,
})),
);
});
Promise.all(promises).then(data => {
const queryDataCopy = { ...queryData };
queryDataCopy.data = [].concat(...data);
// add null values at the edges to fix multiChart bug when series with
// different x values use different y axes
if (lineCharts.length && lineCharts2.length) {
let minX = Infinity;
let maxX = -Infinity;
queryDataCopy.data.forEach(datum => {
minX = Math.min(minX, ...datum.values.map(v => v.x));
maxX = Math.max(maxX, ...datum.values.map(v => v.x));
});
// add null values at the edges
queryDataCopy.data.forEach(datum => {
datum.values.push({ x: minX, y: null });
datum.values.push({ x: maxX, y: null });
});
}
this.setState({ queryData: queryDataCopy });
});
}
render() {
const {
width,
height,
annotationData,
datasource,
formData,
onAddFilter,
onError,
} = this.props;
const { queryData } = this.state;
return (
<ReactNVD3
{...transformProps({
width,
height,
annotationData,
datasource,
formData,
onError,
onAddFilter,
queryData,
})}
/>
);
}
}
LineMulti.propTypes = propTypes;
LineMulti.defaultProps = defaultProps;
export default LineMulti;

View File

@ -1,38 +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 { t } from '@superset-ui/translation';
import { ChartMetadata, ChartPlugin } from '@superset-ui/chart';
import thumbnail from './images/thumbnail.png';
const metadata = new ChartMetadata({
credits: ['http://nvd3.org'],
description: '',
name: t('Multiple Line Charts'),
thumbnail,
useLegacyApi: true,
});
export default class LineChartPlugin extends ChartPlugin {
constructor() {
super({
loadChart: () => import('./LineMulti'),
metadata,
});
}
}

View File

@ -1,123 +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.
*/
.superset-legacy-chart-nvd3-dist-bar {
overflow-x: auto !important;
}
.superset-legacy-chart-nvd3-dist-bar svg.nvd3-svg {
width: auto;
font-size: 14px;
}
.superset-legacy-chart-nvd3-bar {
overflow-x: auto !important;
}
.superset-legacy-chart-nvd3-bar svg.nvd3-svg {
width: auto;
}
.superset-legacy-chart-nvd3 .nv-x text{
font-size: 12px;
}
.superset-legacy-chart-nvd3 g.superset path {
stroke-dasharray: 5, 5;
}
.superset-legacy-chart-nvd3 .nvtooltip tr.highlight td {
font-weight: bold;
font-size: 15px !important;
}
.superset-legacy-chart-nvd3 text.nv-axislabel {
font-size: 14px;
}
.superset-legacy-chart-nvd3 text.nv-axislabel {
font-size: 14px !important;
}
.superset-legacy-chart-nvd3 g.solid path, .superset-legacy-chart-nvd3 line.solid {
stroke-dasharray: unset;
}
.superset-legacy-chart-nvd3 g.dashed path, .superset-legacy-chart-nvd3 line.dashed {
stroke-dasharray: 5, 5;
}
.superset-legacy-chart-nvd3 g.longDashed path, .superset-legacy-chart-nvd3 line.longDashed {
stroke-dasharray: 10, 2;
}
.superset-legacy-chart-nvd3 g.dotted path, .superset-legacy-chart-nvd3 line.dotted {
stroke-dasharray: 1, 1;
}
.superset-legacy-chart-nvd3 g.opacityLow path, .superset-legacy-chart-nvd3 line.opacityLow {
stroke-opacity: .2
}
.superset-legacy-chart-nvd3 g.opacityMedium path, .superset-legacy-chart-nvd3 line.opacityMedium {
stroke-opacity: .5
}
.superset-legacy-chart-nvd3 g.opacityHigh path, .superset-legacy-chart-nvd3 line.opacityHigh {
stroke-opacity: .8
}
.superset-legacy-chart-nvd3 g.time-shift-0 path, .superset-legacy-chart-nvd3 line.time-shift-0 {
stroke-dasharray: 5, 5;
}
.superset-legacy-chart-nvd3 g.time-shift-1 path, .superset-legacy-chart-nvd3 line.time-shift-1 {
stroke-dasharray: 1, 5;
}
.superset-legacy-chart-nvd3 g.time-shift-2 path, .superset-legacy-chart-nvd3 line.time-shift-2 {
stroke-dasharray: 10, 5;
}
.superset-legacy-chart-nvd3 g.time-shift-3 path, .superset-legacy-chart-nvd3 line.time-shift-3 {
stroke-dasharray: 5, 1;
}
.superset-legacy-chart-nvd3 g.time-shift-4 path, .superset-legacy-chart-nvd3 line.time-shift-4 {
stroke-dasharray: 5, 10;
}
.superset-legacy-chart-nvd3 g.time-shift-5 path, .superset-legacy-chart-nvd3 line.time-shift-5 {
stroke-dasharray: 0.9;
}
.superset-legacy-chart-nvd3 g.time-shift-6 path, .superset-legacy-chart-nvd3 line.time-shift-6 {
stroke-dasharray: 15, 10, 5;
}
.superset-legacy-chart-nvd3 g.time-shift-7 path, .superset-legacy-chart-nvd3 line.time-shift-7 {
stroke-dasharray: 15, 10, 5, 10;
}
.superset-legacy-chart-nvd3 g.time-shift-8 path, .superset-legacy-chart-nvd3 line.time-shift-8 {
stroke-dasharray: 15, 10, 5, 10, 15;
}
.superset-legacy-chart-nvd3 g.time-shift-9 path, .superset-legacy-chart-nvd3 line.time-shift-9 {
stroke-dasharray: 5, 5, 1, 5;
}
.superset-legacy-chart-nvd3-tr-highlight {
border-top: 1px solid;
border-bottom: 1px solid;
font-weight: bold;
}
.superset-legacy-chart-nvd3-tr-total {
font-weight: bold;
}

View File

@ -1,40 +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 { t } from '@superset-ui/translation';
import { ChartMetadata, ChartPlugin } from '@superset-ui/chart';
import transformProps from '../transformProps';
import thumbnail from './images/thumbnail.png';
const metadata = new ChartMetadata({
credits: ['http://nvd3.org'],
description: '',
name: t('Pie Chart'),
thumbnail,
useLegacyApi: true,
});
export default class PieChartPlugin extends ChartPlugin {
constructor() {
super({
loadChart: () => import('../ReactNVD3'),
metadata,
transformProps,
});
}
}

View File

@ -1,79 +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.
*/
/* eslint-disable sort-keys */
import PropTypes from 'prop-types';
import { ANNOTATION_TYPES } from './vendor/superset/AnnotationTypes';
export const numberOrAutoType = PropTypes.oneOfType([PropTypes.number, PropTypes.oneOf(['auto'])]);
export const stringOrObjectWithLabelType = PropTypes.oneOfType([
PropTypes.string,
PropTypes.shape({
label: PropTypes.string,
}),
]);
export const rgbObjectType = PropTypes.shape({
r: PropTypes.number.isRequired,
g: PropTypes.number.isRequired,
b: PropTypes.number.isRequired,
});
export const numericXYType = PropTypes.shape({
x: PropTypes.number,
y: PropTypes.number,
});
export const categoryAndValueXYType = PropTypes.shape({
x: PropTypes.string,
y: PropTypes.number,
});
export const boxPlotValueType = PropTypes.shape({
outliers: PropTypes.arrayOf(PropTypes.number),
Q1: PropTypes.number,
Q2: PropTypes.number,
Q3: PropTypes.number,
whisker_high: PropTypes.number,
whisker_low: PropTypes.number,
});
export const bulletDataType = PropTypes.shape({
markerLabels: PropTypes.arrayOf(PropTypes.string),
markerLineLabels: PropTypes.arrayOf(PropTypes.string),
markerLines: PropTypes.arrayOf(PropTypes.number),
markers: PropTypes.arrayOf(PropTypes.number),
measures: PropTypes.arrayOf(PropTypes.number),
rangeLabels: PropTypes.arrayOf(PropTypes.string),
ranges: PropTypes.arrayOf(PropTypes.number),
});
export const annotationLayerType = PropTypes.shape({
annotationType: PropTypes.oneOf(Object.keys(ANNOTATION_TYPES)),
color: PropTypes.string,
hideLine: PropTypes.bool,
name: PropTypes.string,
opacity: PropTypes.string,
show: PropTypes.bool,
showMarkers: PropTypes.bool,
sourceType: PropTypes.string,
style: PropTypes.string,
value: PropTypes.number,
width: PropTypes.number,
});

View File

@ -1,32 +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 { reactify } from '@superset-ui/chart';
import Component from './NVD3Vis';
import { hideTooltips, removeTooltip } from './utils';
function componentWillUnmount() {
const { id } = this.props; // eslint-disable-line babel/no-invalid-this
if (id !== null && id !== undefined) {
removeTooltip(id);
} else {
hideTooltips(true);
}
}
export default reactify(Component, { componentWillUnmount });

View File

@ -1,40 +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 { t } from '@superset-ui/translation';
import { ChartMetadata, ChartPlugin } from '@superset-ui/chart';
import transformProps from '../transformProps';
import thumbnail from './images/thumbnail.png';
const metadata = new ChartMetadata({
credits: ['http://nvd3.org'],
description: '',
name: t('Time-series Period Pivot'),
thumbnail,
useLegacyApi: true,
});
export default class TimePivotChartPlugin extends ChartPlugin {
constructor() {
super({
loadChart: () => import('../ReactNVD3'),
metadata,
transformProps,
});
}
}

View File

@ -1,13 +0,0 @@
export { default as NVD3ChartPreset } from './preset';
export { default as AreaChartPlugin } from './Area';
export { default as BarChartPlugin } from './Bar';
export { default as BoxPlotChartPlugin } from './BoxPlot';
export { default as BubbleChartPlugin } from './Bubble';
export { default as BulletChartPlugin } from './Bullet';
export { default as CompareChartPlugin } from './Compare';
export { default as DistBarChartPlugin } from './DistBar';
export { default as DualLineChartPlugin } from './DualLine';
export { default as LineChartPlugin } from './Line';
export { default as LineMultiChartPlugin } from './LineMulti';
export { default as PieChartPlugin } from './Pie';
export { default as TimePivotChartPlugin } from './TimePivot';

View File

@ -1,53 +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 { Preset } from '@superset-ui/core';
import AreaChartPlugin from './Area';
import BarChartPlugin from './Bar';
import BoxPlotChartPlugin from './BoxPlot';
import BubbleChartPlugin from './Bubble';
import BulletChartPlugin from './Bullet';
import CompareChartPlugin from './Compare';
import DistBarChartPlugin from './DistBar';
import DualLineChartPlugin from './DualLine';
import LineChartPlugin from './Line';
import LineMultiChartPlugin from './LineMulti';
import PieChartPlugin from './Pie';
import TimePivotChartPlugin from './TimePivot';
export default class NVD3ChartPreset extends Preset {
constructor() {
super({
name: 'NVD3 charts',
plugins: [
new AreaChartPlugin().configure({ key: 'area' }),
new BarChartPlugin().configure({ key: 'bar' }),
new BoxPlotChartPlugin().configure({ key: 'box_plot' }),
new BubbleChartPlugin().configure({ key: 'bubble' }),
new BulletChartPlugin().configure({ key: 'bullet' }),
new CompareChartPlugin().configure({ key: 'compare' }),
new DistBarChartPlugin().configure({ key: 'dist_bar' }),
new DualLineChartPlugin().configure({ key: 'dual_line' }),
new LineChartPlugin().configure({ key: 'line' }),
new LineMultiChartPlugin().configure({ key: 'line_multi' }),
new PieChartPlugin().configure({ key: 'pie' }),
new TimePivotChartPlugin().configure({ key: 'time_pivot' }),
],
});
}
}

View File

@ -1,134 +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.
*/
/* eslint-disable sort-keys */
import isTruthy from './utils/isTruthy';
import { formatLabel } from './utils';
const NOOP = () => {};
export default function transformProps(chartProps) {
const { width, height, annotationData, datasource, formData, hooks, queryData } = chartProps;
const { onAddFilter = NOOP, onError = NOOP } = hooks;
const {
annotationLayers,
barStacked,
bottomMargin,
colorPicker,
colorScheme,
comparisonType,
contribution,
donut,
entity,
labelsOutside,
leftMargin,
lineInterpolation,
maxBubbleSize,
orderBars,
pieLabelType,
reduceXTicks,
richTooltip,
sendTimeRange,
showBarValue,
showBrush,
showControls,
showLabels,
showLegend,
showMarkers,
size,
stackedStyle,
vizType,
x,
xAxisFormat,
xAxisLabel,
xAxisShowminmax,
numberFormat,
xLogScale,
xTicksLayout,
y,
yAxisFormat,
yAxis2Format,
yAxisBounds,
yAxisLabel,
yAxisShowminmax,
yLogScale,
} = formData;
const rawData = queryData.data || [];
const data = Array.isArray(rawData)
? rawData.map(row => ({
...row,
key: formatLabel(row.key, datasource.verboseMap),
}))
: rawData;
return {
width,
height,
data,
annotationData,
annotationLayers,
areaStackedStyle: stackedStyle,
baseColor: colorPicker,
bottomMargin,
colorScheme,
comparisonType,
contribution,
entity,
isBarStacked: barStacked,
isDonut: donut,
isPieLabelOutside: labelsOutside,
leftMargin,
lineInterpolation,
maxBubbleSize: parseInt(maxBubbleSize, 10),
numberFormat,
onBrushEnd: isTruthy(sendTimeRange)
? timeRange => {
onAddFilter('__time_range', timeRange, false, true);
}
: undefined,
onError,
orderBars,
pieLabelType,
reduceXTicks,
showBarValue,
showBrush,
showControls,
showLabels,
showLegend,
showMarkers,
sizeField: size,
useRichTooltip: richTooltip,
vizType,
xAxisFormat,
xAxisLabel,
xAxisShowMinMax: xAxisShowminmax,
xField: x,
xIsLogScale: xLogScale,
xTicksLayout,
yAxisFormat,
yAxis2Format,
yAxisBounds,
yAxisLabel,
yAxisShowMinMax: yAxisShowminmax,
yField: y,
yIsLogScale: yLogScale,
};
}

View File

@ -1,396 +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.
*/
/* eslint-disable babel/no-invalid-this, no-magic-numbers */
import d3 from 'd3';
import d3tip from 'd3-tip';
import dompurify from 'dompurify';
import { getNumberFormatter } from '@superset-ui/number-format';
import { smartDateFormatter } from '@superset-ui/time-format';
// Regexp for the label added to time shifted series
// (1 hour offset, 2 days offset, etc.)
const TIME_SHIFT_PATTERN = /\d+ \w+ offset/;
const ANIMATION_TIME = 1000;
export function cleanColorInput(value) {
// for superset series that should have the same color
return String(value)
.trim()
.replace(' (right axis)', '')
.split(', ')
.filter(k => !TIME_SHIFT_PATTERN.test(k))
.join(', ');
}
/**
* If format is smart_date, format date
* Otherwise, format number with the given format name
* @param {*} format
*/
export function getTimeOrNumberFormatter(format) {
return format === 'smart_date' ? smartDateFormatter : getNumberFormatter(format);
}
export function drawBarValues(svg, data, stacked, axisFormat) {
const format = getNumberFormatter(axisFormat);
const countSeriesDisplayed = data.filter(d => !d.disabled).length;
const totalStackedValues =
stacked && data.length !== 0
? data[0].values.map((bar, iBar) => {
const bars = data.filter(series => !series.disabled).map(series => series.values[iBar]);
return d3.sum(bars, d => d.y);
})
: [];
svg.selectAll('.bar-chart-label-group').remove();
setTimeout(() => {
const groupLabels = svg
.select('g.nv-barsWrap')
.append('g')
.attr('class', 'bar-chart-label-group');
svg
.selectAll('g.nv-group')
.filter((d, i) => !stacked || i === countSeriesDisplayed - 1)
.selectAll('rect')
.each(function each(d, index) {
const rectObj = d3.select(this);
const transformAttr = rectObj.attr('transform');
const xPos = parseFloat(rectObj.attr('x'));
const yPos = parseFloat(rectObj.attr('y'));
const rectWidth = parseFloat(rectObj.attr('width'));
const rectHeight = parseFloat(rectObj.attr('height'));
const textEls = groupLabels
.append('text')
.text(format(stacked ? totalStackedValues[index] : d.y))
.attr('transform', transformAttr)
.attr('class', 'bar-chart-label');
// fine tune text position
const bbox = textEls.node().getBBox();
const labelWidth = bbox.width;
const labelHeight = bbox.height;
textEls.attr('x', xPos + rectWidth / 2 - labelWidth / 2);
if (rectObj.attr('class').includes('positive')) {
textEls.attr('y', yPos - 5);
} else {
textEls.attr('y', yPos + rectHeight + labelHeight);
}
});
}, ANIMATION_TIME);
}
// Formats the series key to account for a possible NULL value
function getFormattedKey(seriesKey, shouldDompurify) {
if (seriesKey === '<NULL>') {
return `&lt;${seriesKey.slice(1, -1)}&gt;`;
}
return shouldDompurify ? dompurify.sanitize(seriesKey) : seriesKey;
}
// Custom sorted tooltip
// use a verbose formatter for times
export function generateRichLineTooltipContent(d, timeFormatter, valueFormatter) {
let tooltip = '';
tooltip +=
"<table><thead><tr><td colspan='3'>" +
`<strong class='x-value'>${timeFormatter(d.value)}</strong>` +
'</td></tr></thead><tbody>';
d.series.sort((a, b) => (a.value >= b.value ? -1 : 1));
d.series.forEach(series => {
const key = getFormattedKey(series.key, true);
tooltip +=
`<tr class="${series.highlight ? 'emph' : ''}">` +
`<td class='legend-color-guide' style="opacity: ${series.highlight ? '1' : '0.75'};"">` +
'<div ' +
`style="border: 2px solid ${series.highlight ? 'black' : 'transparent'}; background-color: ${
series.color
};"` +
'></div>' +
'</td>' +
`<td>${key}</td>` +
`<td>${valueFormatter(series.value)}</td>` +
'</tr>';
});
tooltip += '</tbody></table>';
return dompurify.sanitize(tooltip);
}
export function generateAreaChartTooltipContent(d, timeFormatter, valueFormatter) {
const total = d.series[d.series.length - 1].value;
let tooltip = '';
tooltip +=
"<table><thead><tr><td colspan='4'>" +
`<strong class='x-value'>${timeFormatter(d.value)}</strong>` +
'</td></tr></thead><tbody>' +
'<tr><td></td><td>Category</td><td>Value</td><td>% to total</td></tr>';
d.series.forEach(series => {
const key = getFormattedKey(series.key, true);
let trClass = '';
if (series.highlight) {
trClass = 'superset-legacy-chart-nvd3-tr-highlight';
} else if (series.key === 'TOTAL') {
trClass = 'superset-legacy-chart-nvd3-tr-total';
}
tooltip +=
`<tr class="${trClass}" style="border-color: ${series.color}">` +
`<td style="color: ${series.color}">${series.key === 'TOTAL' ? '' : '&#9724;'}</td>` +
`<td>${key}</td>` +
`<td>${valueFormatter(series.value)}</td>` +
`<td>${((100 * series.value) / total).toFixed(2)}%</td>` +
'</tr>';
});
tooltip += '</tbody></table>';
return dompurify.sanitize(tooltip);
}
export function generateMultiLineTooltipContent(d, xFormatter, yFormatters) {
const tooltipTitle = xFormatter(d.value);
let tooltip = '';
tooltip +=
"<table><thead><tr><td colspan='3'>" +
`<strong class='x-value'>${tooltipTitle}</strong>` +
'</td></tr></thead><tbody>';
d.series.forEach((series, i) => {
const yFormatter = yFormatters[i];
const key = getFormattedKey(series.key, false);
tooltip +=
"<tr><td class='legend-color-guide'>" +
`<div style="background-color: ${series.color};"></div></td>` +
`<td class='key'>${key}</td>` +
`<td class='value'>${yFormatter(series.value)}</td></tr>`;
});
tooltip += '</tbody></table>';
return tooltip;
}
export function generateTimePivotTooltip(d, xFormatter, yFormatter) {
const tooltipTitle = xFormatter(d.value);
let tooltip = '';
tooltip +=
"<table><thead><tr><td colspan='3'>" +
`<strong class='x-value'>${tooltipTitle}</strong>` +
'</td></tr></thead><tbody>';
d.series.forEach(series => {
if (series.highlight) {
let label = '';
if (series.key === 'current') {
label = series.key;
} else {
label = `${series.key} of the selected frequency:`;
}
tooltip +=
"<tr><td class='legend-color-guide'>" +
`<div style="background-color: ${series.color};"></div></td>` +
`<td class='key'>${label}</td>` +
`<td class='value'>${yFormatter(series.value)}</td></tr>`;
}
});
tooltip += '</tbody></table>';
return dompurify.sanitize(tooltip);
}
function getLabel(stringOrObjectWithLabel) {
return stringOrObjectWithLabel.label || stringOrObjectWithLabel;
}
function createHTMLRow(col1, col2) {
return `<tr><td>${col1}</td><td>${col2}</td></tr>`;
}
export function generateBubbleTooltipContent({
point,
entity,
xField,
yField,
sizeField,
xFormatter,
yFormatter,
sizeFormatter,
}) {
let s = '<table>';
s +=
`<tr><td style="color: ${point.color};">` +
`<strong>${point[entity]}</strong> (${point.group})` +
'</td></tr>';
s += createHTMLRow(getLabel(xField), xFormatter(point.x));
s += createHTMLRow(getLabel(yField), yFormatter(point.y));
s += createHTMLRow(getLabel(sizeField), sizeFormatter(point.size));
s += '</table>';
return s;
}
// shouldRemove indicates whether the nvtooltips should be removed from the DOM
export function hideTooltips(shouldRemove) {
const targets = document.querySelectorAll('.nvtooltip');
if (targets.length > 0) {
// Only set opacity to 0 when hiding tooltips so they would reappear
// on hover, which sets the opacity to 1
targets.forEach(t => {
if (shouldRemove) {
t.remove();
} else {
// eslint-disable-next-line no-param-reassign
t.style.opacity = 0;
}
});
}
}
export function generateTooltipClassName(uuid) {
return `tooltip-${uuid}`;
}
export function removeTooltip(uuid) {
const classSelector = `.${generateTooltipClassName(uuid)}`;
const target = document.querySelector(classSelector);
if (target) {
target.remove();
}
}
export function wrapTooltip(chart, maxWidth) {
const tooltipLayer =
chart.useInteractiveGuideline && chart.useInteractiveGuideline()
? chart.interactiveLayer
: chart;
const tooltipGeneratorFunc = tooltipLayer.tooltip.contentGenerator();
tooltipLayer.tooltip.contentGenerator(d => {
let tooltip = `<div style="max-width: ${maxWidth * 0.5}px">`;
tooltip += tooltipGeneratorFunc(d);
tooltip += '</div>';
return tooltip;
});
}
export function tipFactory(layer) {
return d3tip()
.attr('class', 'd3-tip')
.direction('n')
.offset([-5, 0])
.html(d => {
if (!d) {
return '';
}
const title =
d[layer.titleColumn] && d[layer.titleColumn].length
? `${d[layer.titleColumn]} - ${layer.name}`
: layer.name;
const body = Array.isArray(layer.descriptionColumns)
? layer.descriptionColumns.map(c => d[c])
: /* eslint-disable-next-line compat/compat */
Object.values(d);
return `<div><strong>${title}</strong></div><br/><div>${body.join(', ')}</div>`;
});
}
export function getMaxLabelSize(svg, axisClass) {
// axis class = .nv-y2 // second y axis on dual line chart
// axis class = .nv-x // x axis on time series line chart
const tickTexts = svg.selectAll(`.${axisClass} g.tick text`);
if (tickTexts.length > 0) {
const lengths = tickTexts[0].map(text => text.getComputedTextLength());
return Math.ceil(Math.max(0, ...lengths));
}
return 0;
}
export function formatLabel(input, verboseMap = {}) {
// The input for label may be a string or an array of string
// When using the time shift feature, the label contains a '---' in the array
const verboseLookup = s => verboseMap[s] || s;
return Array.isArray(input) && input.length
? input.map(l => (TIME_SHIFT_PATTERN.test(l) ? l : verboseLookup(l))).join(', ')
: verboseLookup(input);
}
const MIN_BAR_WIDTH = 18;
export function computeBarChartWidth(data, stacked, maxWidth) {
const barCount = stacked
? d3.max(data, d => d.values.length)
: d3.sum(data, d => d.values.length);
const barWidth = barCount * MIN_BAR_WIDTH;
return Math.max(barWidth, maxWidth);
}
export function tryNumify(s) {
// Attempts casting to Number, returns string when failing
const n = Number(s);
return Number.isNaN(n) ? s : n;
}
export function stringifyTimeRange(extent) {
if (extent.some(d => d.toISOString === undefined)) {
return null;
}
return extent.map(d => d.toISOString().slice(0, -1)).join(' : ');
}
export function setAxisShowMaxMin(axis, showminmax) {
if (axis && axis.showMaxMin && showminmax !== undefined) {
axis.showMaxMin(showminmax);
}
}
export function computeYDomain(data) {
if (Array.isArray(data) && data.length > 0 && Array.isArray(data[0].values)) {
const extents = data.filter(d => !d.disabled).map(row => d3.extent(row.values, v => v.y));
const minOfMin = d3.min(extents, ([min]) => min);
const maxOfMax = d3.max(extents, ([, max]) => max);
return [minOfMin, maxOfMax];
}
return [0, 1];
}
export function computeStackedYDomain(data) {
if (Array.isArray(data) && data.length > 0 && Array.isArray(data[0].values)) {
const series = data.filter(d => !d.disabled).map(d => d.values.map(v => v.y));
const stackedValues = series[0].map((_, i) => series.reduce((acc, cur) => acc + cur[i], 0));
return [Math.min(0, ...stackedValues), Math.max(0, ...stackedValues)];
}
return [0, 1];
}

View File

@ -1,9 +0,0 @@
export default function isTruthy(obj) {
if (typeof obj === 'boolean') {
return obj;
} else if (typeof obj === 'string') {
return ['yes', 'y', 'true', 't', '1'].indexOf(obj.toLowerCase()) >= 0;
}
return !!obj;
}

View File

@ -1,82 +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.
*/
/* eslint-disable sort-keys */
function extractTypes(metadata) {
return Object.keys(metadata).reduce((prev, key) => {
const result = prev;
result[key] = key;
return result;
}, {});
}
export const ANNOTATION_TYPES_METADATA = {
FORMULA: {
value: 'FORMULA',
label: 'Formula',
},
EVENT: {
value: 'EVENT',
label: 'Event',
supportNativeSource: true,
},
INTERVAL: {
value: 'INTERVAL',
label: 'Interval',
supportNativeSource: true,
},
TIME_SERIES: {
value: 'TIME_SERIES',
label: 'Time Series',
},
};
export const ANNOTATION_TYPES = extractTypes(ANNOTATION_TYPES_METADATA);
export const DEFAULT_ANNOTATION_TYPE = ANNOTATION_TYPES.FORMULA;
export const ANNOTATION_SOURCE_TYPES_METADATA = {
NATIVE: {
value: 'NATIVE',
label: 'Superset annotation',
},
};
export const ANNOTATION_SOURCE_TYPES = extractTypes(ANNOTATION_SOURCE_TYPES_METADATA);
export function requiresQuery(annotationSourceType) {
return !!annotationSourceType;
}
const NATIVE_COLUMN_NAMES = {
descriptionColumns: ['long_descr'],
intervalEndColumn: 'end_dttm',
timeColumn: 'start_dttm',
titleColumn: 'short_descr',
};
export function applyNativeColumns(annotation) {
if (annotation.sourceType === ANNOTATION_SOURCE_TYPES.NATIVE) {
return { ...annotation, ...NATIVE_COLUMN_NAMES };
}
return annotation;
}
export default ANNOTATION_TYPES;

View File

@ -1,66 +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.
*/
/* eslint camelcase: 0 */
import URI from 'urijs';
import safeStringify from 'fast-safe-stringify';
const MAX_URL_LENGTH = 8000;
export function getURIDirectory(formData, endpointType = 'base') {
// Building the directory part of the URI
let directory = '/superset/explore/';
if (['json', 'csv', 'query', 'results', 'samples'].indexOf(endpointType) >= 0) {
directory = '/superset/explore_json/';
}
return directory;
}
export function getExploreLongUrl(formData, endpointType, allowOverflow = true, extraSearch = {}) {
if (!formData.datasource) {
return null;
}
const uri = new URI('/');
const directory = getURIDirectory(formData, endpointType);
const search = uri.search(true);
Object.keys(extraSearch).forEach(key => {
search[key] = extraSearch[key];
});
search.form_data = safeStringify(formData);
if (endpointType === 'standalone') {
search.standalone = 'true';
}
const url = uri
.directory(directory)
.search(search)
.toString();
if (!allowOverflow && url.length > MAX_URL_LENGTH) {
const minimalFormData = {
datasource: formData.datasource,
viz_type: formData.viz_type,
};
return getExploreLongUrl(minimalFormData, endpointType, false, {
URL_IS_TOO_LONG_TO_SHARE: null,
});
}
return url;
}

View File

@ -1,189 +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 {
computeStackedYDomain,
computeYDomain,
getTimeOrNumberFormatter,
formatLabel,
tryNumify,
} from '../src/utils';
const DATA = [
{
key: ['East Asia & Pacific'],
values: [
{
x: -315619200000.0,
y: 1031863394.0,
},
{
x: -283996800000.0,
y: 1034767718.0,
},
],
},
{
key: ['South Asia'],
values: [
{
x: -315619200000.0,
y: 572036107.0,
},
{
x: -283996800000.0,
y: 584143236.0,
},
],
},
{
key: ['Europe & Central Asia'],
values: [
{
x: -315619200000.0,
y: 660881033.0,
},
{
x: -283996800000.0,
y: 668526708.0,
},
],
},
];
const DATA_WITH_DISABLED_SERIES = [
{
disabled: true,
key: ['East Asia & Pacific'],
values: [
{
x: -315619200000.0,
y: 1031863394.0,
},
{
x: -283996800000.0,
y: 1034767718.0,
},
],
},
{
disabled: true,
key: ['South Asia'],
values: [
{
x: -315619200000.0,
y: 572036107.0,
},
{
x: -283996800000.0,
y: 584143236.0,
},
],
},
{
key: ['Europe & Central Asia'],
values: [
{
x: -315619200000.0,
y: 660881033.0,
},
{
x: -283996800000.0,
y: 668526708.0,
},
],
},
];
describe('nvd3/utils', () => {
describe('getTimeOrNumberFormatter(format)', () => {
it('is a function', () => {
expect(typeof getTimeOrNumberFormatter).toBe('function');
});
it('returns a date formatter if format is smart_date', () => {
const time = new Date(Date.UTC(2018, 10, 21, 22, 11));
expect(getTimeOrNumberFormatter('smart_date')(time)).toBe('10:11');
});
it('returns a number formatter otherwise', () => {
expect(getTimeOrNumberFormatter('.3s')(3000000)).toBe('3.00M');
expect(getTimeOrNumberFormatter()(3000100)).toBe('3M');
});
});
describe('formatLabel()', () => {
const verboseMap = {
foo: 'Foo',
bar: 'Bar',
};
it('formats simple labels', () => {
expect(formatLabel('foo')).toBe('foo');
expect(formatLabel(['foo'])).toBe('foo');
expect(formatLabel(['foo', 'bar'])).toBe('foo, bar');
});
it('formats simple labels with lookups', () => {
expect(formatLabel('foo', verboseMap)).toBe('Foo');
expect(formatLabel('baz', verboseMap)).toBe('baz');
expect(formatLabel(['foo'], verboseMap)).toBe('Foo');
expect(formatLabel(['foo', 'bar', 'baz'], verboseMap)).toBe('Foo, Bar, baz');
});
it('deals with time shift properly', () => {
expect(formatLabel(['foo', '1 hour offset'], verboseMap)).toBe('Foo, 1 hour offset');
expect(formatLabel(['foo', 'bar', 'baz', '2 hours offset'], verboseMap)).toBe(
'Foo, Bar, baz, 2 hours offset',
);
});
});
describe('tryNumify()', () => {
it('tryNumify works as expected', () => {
expect(tryNumify(5)).toBe(5);
expect(tryNumify('5')).toBe(5);
expect(tryNumify('5.1')).toBe(5.1);
expect(tryNumify('a string')).toBe('a string');
});
});
describe('computeYDomain()', () => {
it('works with invalid data', () => {
expect(computeYDomain('foo')).toEqual([0, 1]);
});
it('works with all series enabled', () => {
expect(computeYDomain(DATA)).toEqual([572036107.0, 1034767718.0]);
});
it('works with some series disabled', () => {
expect(computeYDomain(DATA_WITH_DISABLED_SERIES)).toEqual([660881033.0, 668526708.0]);
});
});
describe('computeStackedYDomain()', () => {
it('works with invalid data', () => {
expect(computeStackedYDomain('foo')).toEqual([0, 1]);
});
it('works with all series enabled', () => {
expect(computeStackedYDomain(DATA)).toEqual([0, 2287437662.0]);
});
it('works with some series disabled', () => {
expect(computeStackedYDomain(DATA_WITH_DISABLED_SERIES)).toEqual([0, 668526708.0]);
});
});
});

View File

@ -1,39 +0,0 @@
import isTruthy from '../../src/utils/isTruthy';
describe('isTruthy', () => {
it('evals false-looking strings properly', () => {
expect(isTruthy('f')).toBe(false);
expect(isTruthy('false')).toBe(false);
expect(isTruthy('no')).toBe(false);
expect(isTruthy('n')).toBe(false);
expect(isTruthy('F')).toBe(false);
expect(isTruthy('False')).toBe(false);
expect(isTruthy('NO')).toBe(false);
expect(isTruthy('N')).toBe(false);
});
it('evals true-looking strings properly', () => {
expect(isTruthy('t')).toBe(true);
expect(isTruthy('true')).toBe(true);
expect(isTruthy('yes')).toBe(true);
expect(isTruthy('y')).toBe(true);
expect(isTruthy('Y')).toBe(true);
expect(isTruthy('True')).toBe(true);
expect(isTruthy('Yes')).toBe(true);
expect(isTruthy('YES')).toBe(true);
});
it('evals bools properly', () => {
expect(isTruthy(false)).toBe(false);
expect(isTruthy(true)).toBe(true);
});
it('evals ints properly', () => {
expect(isTruthy(0)).toBe(false);
expect(isTruthy(1)).toBe(true);
});
it('evals constants properly', () => {
expect(isTruthy(null)).toBe(false);
expect(isTruthy(undefined)).toBe(false);
});
it('string auto is false', () => {
expect(isTruthy('false')).toBe(false);
});
});

View File

@ -9,7 +9,6 @@ const BABEL_TYPESCRIPT_OPTIONS = {
'@babel/preset-typescript',
],
plugins: [
'lodash',
'@babel/plugin-proposal-object-rest-spread',
'@babel/plugin-proposal-class-properties',
'@babel/plugin-syntax-dynamic-import',

View File

@ -0,0 +1,60 @@
/* eslint-disable no-magic-numbers */
import React from 'react';
import { SuperChart } from '@superset-ui/chart';
import payload from './payload';
import dummyDatasource from '../../../shared/dummyDatasource';
export default [
{
renderStory: () => (
<SuperChart
chartType="deck_path"
width={400}
height={400}
datasource={dummyDatasource}
queryData={payload}
formData={{
datasource: '11__table',
viz_type: 'deck_path',
slice_id: 72,
url_params: {},
granularity_sqla: null,
time_grain_sqla: null,
time_range: '+:+',
line_column: 'path_json',
line_type: 'json',
row_limit: 5000,
filter_nulls: true,
adhoc_filters: [],
mapbox_style: 'mapbox://styles/mapbox/light-v9',
viewport: {
altitude: 1.5,
bearing: 0,
height: 1094,
latitude: 37.73671752604488,
longitude: -122.18885402582598,
maxLatitude: 85.05113,
maxPitch: 60,
maxZoom: 20,
minLatitude: -85.05113,
minPitch: 0,
minZoom: 0,
pitch: 0,
width: 669,
zoom: 9.51847667620428,
},
color_picker: { a: 1, b: 135, g: 122, r: 0 },
line_width: 150,
reverse_long_lat: false,
autozoom: true,
js_columns: ['color'],
js_data_mutator: '',
js_tooltip: '',
js_onclick_href: '',
}}
/>
),
storyName: 'Basic',
storyPath: 'legacy-|preset-chart-deckgl|PathChartPlugin',
},
];

View File

@ -0,0 +1,8 @@
import { PathChartPlugin } from '../../../../../superset-ui-legacy-preset-chart-deckgl/src';
import Stories from './Stories';
new PathChartPlugin().configure({ key: 'deck_path' }).register();
export default {
examples: [...Stories],
};

View File

@ -0,0 +1,207 @@
export default {
cache_key: null,
cached_dttm: null,
cache_timeout: 86400,
error: null,
form_data: {
datasource: '11__table',
viz_type: 'deck_path',
slice_id: 72,
url_params: {},
granularity_sqla: null,
time_grain_sqla: null,
time_range: ' : ',
line_column: 'path_json',
line_type: 'json',
row_limit: 5000,
filter_nulls: true,
adhoc_filters: [
{
clause: 'WHERE',
expressionType: 'SIMPLE',
filterOptionName: 'b4c1a7de-17ef-4505-b688-2760c0c22e1f',
comparator: '',
operator: 'IS NOT NULL',
subject: 'path_json',
},
],
mapbox_style: 'mapbox://styles/mapbox/light-v9',
viewport: {
altitude: 1.5,
bearing: 0,
height: 1094,
latitude: 37.73671752604488,
longitude: -122.18885402582598,
maxLatitude: 85.05113,
maxPitch: 60,
maxZoom: 20,
minLatitude: -85.05113,
minPitch: 0,
minZoom: 0,
pitch: 0,
width: 669,
zoom: 9.51847667620428,
},
color_picker: { a: 1, b: 135, g: 122, r: 0 },
line_width: 150,
reverse_long_lat: false,
autozoom: true,
js_columns: ['color'],
where: '',
having: '',
having_filters: [],
filters: [{ col: 'path_json', op: 'IS NOT NULL', val: '' }],
},
is_cached: false,
query:
'SELECT color AS color,\n path_json AS path_json\nFROM bart_lines\nWHERE path_json IS NOT NULL\nLIMIT 5000\nOFFSET 0',
status: 'success',
stacktrace: null,
rowcount: 5,
data: {
features: [
{
color: '#ed1c24',
path: [
[-122.3535851, 37.9360513],
[-122.3179784, 37.9249513],
[-122.300284, 37.902646],
[-122.2843653, 37.8735039],
[-122.269058, 37.8694562],
[-122.2709185, 37.85301],
[-122.2689342, 37.8283973],
[-122.2707195, 37.8080566],
[-122.2718706, 37.804996],
[-122.2948251, 37.8064628],
[-122.3971496, 37.794745],
[-122.4030149, 37.7905282],
[-122.4084631, 37.7862646],
[-122.4157833, 37.7803439],
[-122.4219476, 37.7653052],
[-122.4206096, 37.7528545],
[-122.4359052, 37.7340058],
[-122.448995, 37.723273],
[-122.471192, 37.7067871],
[-122.4672607, 37.6842548],
[-122.4449822, 37.6635925],
[-122.4169649, 37.6372339],
[-122.3876274, 37.5993171],
],
__timestamp: null,
extraProps: { color: '#ed1c24' },
},
{
color: '#faa61a',
path: [
[-122.353165, 37.936887],
[-122.317269, 37.925655],
[-122.299272, 37.903059],
[-122.283451, 37.87404],
[-122.268045, 37.869867],
[-122.26978, 37.853024],
[-122.2677961, 37.8284091],
[-122.2695925, 37.8079322],
[-122.2721546, 37.8035508],
[-122.2666476, 37.7964139],
[-122.2253433, 37.7739122],
[-122.1985085, 37.7530763],
[-122.1625282, 37.7216747],
[-122.1280105, 37.6961822],
[-122.0888196, 37.669805],
[-122.0584803, 37.6342836],
[-122.0187396, 37.5906334],
[-121.9772135, 37.5567286],
],
__timestamp: null,
extraProps: { color: '#faa61a' },
},
{
color: '#ffe800',
path: [
[-121.945154, 38.018914],
[-122.024597, 38.003275],
[-122.029095, 37.973737],
[-122.056013, 37.928403],
[-122.067423, 37.905628],
[-122.123801, 37.893394],
[-122.183791, 37.878361],
[-122.251793, 37.844601],
[-122.2666934, 37.8282587],
[-122.2684655, 37.8078078],
[-122.2715151, 37.80322],
[-122.2947035, 37.8055689],
[-122.3969458, 37.7938605],
[-122.402211, 37.7898921],
[-122.40766, 37.7856278],
[-122.4147696, 37.779936],
[-122.4208208, 37.7651836],
[-122.4195378, 37.7525542],
[-122.4349986, 37.7334634],
[-122.4482045, 37.722627],
[-122.4701365, 37.7064541],
[-122.466233, 37.684638],
[-122.444116, 37.664174],
[-122.416038, 37.637753000000004],
[-122.392612, 37.616035],
[-122.38666, 37.599787],
],
__timestamp: null,
extraProps: { color: '#ffe800' },
},
{
color: '#00aeef',
path: [
[-121.900367, 37.701695],
[-121.928099, 37.699759],
[-122.075567, 37.690754],
[-122.1266292, 37.6975918],
[-122.160905, 37.7229335],
[-122.1968609, 37.7543157],
[-122.2239172, 37.7753131],
[-122.2653405, 37.7978803],
[-122.294582, 37.804675],
[-122.396742, 37.792976],
[-122.401407, 37.789256],
[-122.406857, 37.784991],
[-122.413756, 37.779528],
[-122.419694, 37.765062],
[-122.418466, 37.752254],
[-122.434092, 37.732921],
[-122.447414, 37.721981],
[-122.469081, 37.706121],
],
__timestamp: null,
extraProps: { color: '#00aeef' },
},
{
color: '#4db848',
path: [
[-121.9764, 37.557355],
[-122.017867, 37.591208],
[-122.057551, 37.6348],
[-122.087967, 37.670399],
[-122.1272512, 37.696851],
[-122.161717, 37.7223045],
[-122.1976851, 37.7536963],
[-122.2246308, 37.7746129],
[-122.2658775, 37.7970877],
[-122.2945333, 37.8037768],
[-122.3965382, 37.7920915],
[-122.4006031, 37.7886199],
[-122.406054, 37.7843542],
[-122.4127424, 37.77912],
[-122.4185672, 37.7649404],
[-122.4173942, 37.7519538],
[-122.4331854, 37.7323786],
[-122.4466235, 37.721335],
[-122.4683093, 37.705461],
],
__timestamp: null,
extraProps: { color: '#4db848' },
},
],
mapboxApiKey:
'pk.eyJ1Ijoia3Jpc3R3IiwiYSI6ImNqbGg1N242NTFlczczdnBhazViMjgzZ2sifQ.lUneM-o3NucXN189EYyXxQ',
metricLabels: [],
},
};

View File

@ -1,30 +0,0 @@
/* eslint-disable no-magic-numbers */
import React from 'react';
import { SuperChart } from '@superset-ui/chart';
import data from './data';
import dummyDatasource from '../../../shared/dummyDatasource';
export default [
{
renderStory: () => (
<SuperChart
chartType="bullet"
width={400}
height={400}
datasource={dummyDatasource}
queryData={{ data }}
formData={{
markerLabels: '',
markerLineLabels: '',
markerLines: '',
markers: '',
rangeLabels: '',
ranges: '',
vizType: 'bullet',
}}
/>
),
storyName: 'Basic',
storyPath: 'legacy-|preset-chart-nvd3|BulletChartPlugin',
},
];

View File

@ -1,10 +0,0 @@
/* eslint-disable sort-keys, no-magic-numbers */
export default {
measures: [75691],
ranges: [0, 83260.1],
rangeLabels: null,
markers: null,
markerLabels: null,
markerLines: null,
markerLineLabels: null,
};

View File

@ -1,8 +0,0 @@
import { BulletChartPlugin } from '../../../../../superset-ui-legacy-preset-chart-nvd3';
import Stories from './Stories';
new BulletChartPlugin().configure({ key: 'bullet' }).register();
export default {
examples: [...Stories],
};

View File

@ -1,31 +0,0 @@
/* eslint-disable no-magic-numbers */
import React from 'react';
import { SuperChart } from '@superset-ui/chart';
import data from './data';
import dummyDatasource from '../../../shared/dummyDatasource';
export default [
{
renderStory: () => (
<SuperChart
chartType="pie"
width={400}
height={400}
datasource={dummyDatasource}
queryData={{ data }}
formData={{
colorScheme: 'd3Category10',
donut: false,
labelsOutside: true,
numberFormat: '.3s',
pieLabelType: 'key',
showLabels: true,
showLegend: true,
vizType: 'pie',
}}
/>
),
storyName: 'Basic',
storyPath: 'legacy-|preset-chart-nvd3|PieChartPlugin',
},
];

View File

@ -1,11 +0,0 @@
/* eslint-disable sort-keys, no-magic-numbers */
export default [
{
x: 'boy',
y: 48133355,
},
{
x: 'girl',
y: 32546308,
},
];

View File

@ -1,8 +0,0 @@
import { PieChartPlugin } from '../../../../../superset-ui-legacy-preset-chart-nvd3';
import Stories from './Stories';
new PieChartPlugin().configure({ key: 'pie' }).register();
export default {
examples: [...Stories],
};